From: Luka Gejak <luka.gejak@linux.dev>
To: Ping-Ke Shih <pkshih@realtek.com>
Cc: linux-wireless@vger.kernel.org, Luka Gejak <luka.gejak@linux.dev>
Subject: [PATCH rtw-next v2 1/2] wifi: rtw88: move the bmc high queue decision to tx.c
Date: Wed, 21 Oct 2026 12:43:17 +0000 [thread overview]
Message-ID: <20261021124318.15993-1-luka.gejak@linux.dev> (raw)
USB decides in usb.c which broadcast and multicast (bmc) frames may use
the high queue. SDIO needs the same decision, so move the helpers to
tx.c behind a single exported rtw_tx_bmc_use_hiq() and keep the budget
state in struct rtw_dev.
No functional change.
Signed-off-by: Luka Gejak <luka.gejak@linux.dev>
---
drivers/net/wireless/realtek/rtw88/main.c | 3 ++
drivers/net/wireless/realtek/rtw88/main.h | 5 ++
drivers/net/wireless/realtek/rtw88/tx.c | 59 +++++++++++++++++++++
drivers/net/wireless/realtek/rtw88/tx.h | 4 ++
drivers/net/wireless/realtek/rtw88/usb.c | 64 ++---------------------
drivers/net/wireless/realtek/rtw88/usb.h | 5 --
6 files changed, 74 insertions(+), 66 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c
index 0f23498b5c96..b72173964bdd 100644
--- a/drivers/net/wireless/realtek/rtw88/main.c
+++ b/drivers/net/wireless/realtek/rtw88/main.c
@@ -2177,6 +2177,9 @@ int rtw_core_init(struct rtw_dev *rtwdev)
spin_lock_init(&rtwdev->txq_lock);
spin_lock_init(&rtwdev->tx_report.q_lock);
+ spin_lock_init(&rtwdev->hiq_lock);
+ rtwdev->hiq_budget = RTW_TX_HIQ_BUDGET_MAX;
+ rtwdev->hiq_refill = jiffies;
mutex_init(&rtwdev->mutex);
mutex_init(&rtwdev->hal.tx_power_mutex);
diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h
index d59f6e323adf..c14c834c27fd 100644
--- a/drivers/net/wireless/realtek/rtw88/main.h
+++ b/drivers/net/wireless/realtek/rtw88/main.h
@@ -2104,6 +2104,11 @@ struct rtw_dev {
struct rtw_tx_report tx_report;
+ /* protects hiq_budget and hiq_refill */
+ spinlock_t hiq_lock;
+ u32 hiq_budget;
+ unsigned long hiq_refill;
+
struct {
/* indicate the mail box to use with fw */
u8 last_box_num;
diff --git a/drivers/net/wireless/realtek/rtw88/tx.c b/drivers/net/wireless/realtek/rtw88/tx.c
index 701ed7c4f3f7..82c1af94f1cc 100644
--- a/drivers/net/wireless/realtek/rtw88/tx.c
+++ b/drivers/net/wireless/realtek/rtw88/tx.c
@@ -2,6 +2,8 @@
/* Copyright(c) 2018-2019 Realtek Corporation
*/
+#include <linux/ip.h>
+#include <linux/udp.h>
#include "main.h"
#include "tx.h"
#include "fw.h"
@@ -745,3 +747,60 @@ enum rtw_tx_queue_type rtw_tx_queue_mapping(struct sk_buff *skb)
return queue;
}
EXPORT_SYMBOL(rtw_tx_queue_mapping);
+
+static bool rtw_tx_bmc_needs_dtim(struct sk_buff *skb)
+{
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct udphdr *udphdr;
+
+ if (info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO)
+ return true;
+
+ if (skb->protocol == htons(ETH_P_ARP))
+ return true;
+
+ if (skb->protocol == htons(ETH_P_IP) &&
+ ip_hdr(skb)->protocol == IPPROTO_UDP) {
+ udphdr = udp_hdr(skb);
+
+ return udphdr->dest == htons(67) || udphdr->dest == htons(68);
+ }
+
+ return false;
+}
+
+static bool rtw_tx_hiq_take_budget(struct rtw_dev *rtwdev)
+{
+ unsigned long flags, elapsed, add;
+ bool ok;
+
+ spin_lock_irqsave(&rtwdev->hiq_lock, flags);
+
+ elapsed = jiffies - rtwdev->hiq_refill;
+ add = elapsed / RTW_TX_HIQ_REFILL_INTERVAL;
+ if (add) {
+ rtwdev->hiq_budget = min_t(unsigned long, rtwdev->hiq_budget + add,
+ RTW_TX_HIQ_BUDGET_MAX);
+
+ /* keep the unfinished part of the interval for the next unit */
+ rtwdev->hiq_refill = jiffies - elapsed % RTW_TX_HIQ_REFILL_INTERVAL;
+ }
+
+ ok = rtwdev->hiq_budget > 0;
+ if (ok)
+ rtwdev->hiq_budget--;
+
+ spin_unlock_irqrestore(&rtwdev->hiq_lock, flags);
+
+ return ok;
+}
+
+bool rtw_tx_bmc_use_hiq(struct rtw_dev *rtwdev, struct sk_buff *skb)
+{
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+
+ return (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) &&
+ rtw_tx_bmc_needs_dtim(skb) &&
+ rtw_tx_hiq_take_budget(rtwdev);
+}
+EXPORT_SYMBOL(rtw_tx_bmc_use_hiq);
diff --git a/drivers/net/wireless/realtek/rtw88/tx.h b/drivers/net/wireless/realtek/rtw88/tx.h
index 168f48e87853..a68ba3b12159 100644
--- a/drivers/net/wireless/realtek/rtw88/tx.h
+++ b/drivers/net/wireless/realtek/rtw88/tx.h
@@ -10,6 +10,9 @@
#define RTW_TX_PROBE_TIMEOUT_SHORT msecs_to_jiffies(500)
#define RTW_TX_PROBE_TIMEOUT_LONG msecs_to_jiffies(2500)
+#define RTW_TX_HIQ_REFILL_INTERVAL (HZ / 10)
+#define RTW_TX_HIQ_BUDGET_MAX 16
+
struct rtw_tx_desc {
__le32 w0;
__le32 w1;
@@ -115,6 +118,7 @@ rtw_tx_write_data_h2c_get(struct rtw_dev *rtwdev,
enum rtw_tx_queue_type rtw_tx_ac_to_hwq(enum ieee80211_ac_numbers ac);
enum rtw_tx_queue_type rtw_tx_queue_mapping(struct sk_buff *skb);
+bool rtw_tx_bmc_use_hiq(struct rtw_dev *rtwdev, struct sk_buff *skb);
static inline
void fill_txdesc_checksum_common(u8 *txdesc, size_t words)
diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c
index 715a2ce342d9..13adbd415158 100644
--- a/drivers/net/wireless/realtek/rtw88/usb.c
+++ b/drivers/net/wireless/realtek/rtw88/usb.c
@@ -2,10 +2,8 @@
/* Copyright(c) 2018-2019 Realtek Corporation
*/
-#include <linux/ip.h>
#include <linux/module.h>
#include <linux/mutex.h>
-#include <linux/udp.h>
#include <linux/usb.h>
#include "main.h"
#include "debug.h"
@@ -564,61 +562,10 @@ static int rtw_usb_write_data_h2c(struct rtw_dev *rtwdev, u8 *buf, u32 size)
return rtw_usb_write_data(rtwdev, &pkt_info, buf);
}
-static bool rtw_usb_bmc_needs_dtim(struct sk_buff *skb)
-{
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct udphdr *udphdr;
-
- if (info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO)
- return true;
-
- if (skb->protocol == htons(ETH_P_ARP))
- return true;
-
- if (skb->protocol == htons(ETH_P_IP) &&
- ip_hdr(skb)->protocol == IPPROTO_UDP) {
- udphdr = udp_hdr(skb);
-
- return udphdr->dest == htons(67) || udphdr->dest == htons(68);
- }
-
- return false;
-}
-
-#define RTW_USB_HIQ_REFILL_INTERVAL (HZ / 10) /* one unit of budget per 100 ms */
-#define RTW_USB_HIQ_BUDGET_MAX 16
-
-static bool rtw_usb_hiq_take_budget(struct rtw_usb *rtwusb)
-{
- unsigned long flags, elapsed, add;
- bool ok;
-
- spin_lock_irqsave(&rtwusb->hiq_lock, flags);
-
- elapsed = jiffies - rtwusb->hiq_refill;
- add = elapsed / RTW_USB_HIQ_REFILL_INTERVAL;
- if (add) {
- rtwusb->hiq_budget = min_t(unsigned long, rtwusb->hiq_budget + add,
- RTW_USB_HIQ_BUDGET_MAX);
-
- /* keep the unfinished part of the interval for the next unit */
- rtwusb->hiq_refill = jiffies - elapsed % RTW_USB_HIQ_REFILL_INTERVAL;
- }
-
- ok = rtwusb->hiq_budget > 0;
- if (ok)
- rtwusb->hiq_budget--;
-
- spin_unlock_irqrestore(&rtwusb->hiq_lock, flags);
-
- return ok;
-}
-
-static u8 rtw_usb_tx_queue_mapping_to_qsel(struct rtw_usb *rtwusb,
+static u8 rtw_usb_tx_queue_mapping_to_qsel(struct rtw_dev *rtwdev,
struct sk_buff *skb)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
__le16 fc = hdr->frame_control;
u8 qsel;
@@ -626,8 +573,7 @@ static u8 rtw_usb_tx_queue_mapping_to_qsel(struct rtw_usb *rtwusb,
qsel = TX_DESC_QSEL_MGMT;
else if (is_broadcast_ether_addr(hdr->addr1) ||
is_multicast_ether_addr(hdr->addr1))
- qsel = (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) &&
- rtw_usb_bmc_needs_dtim(skb) && rtw_usb_hiq_take_budget(rtwusb) ?
+ qsel = rtw_tx_bmc_use_hiq(rtwdev, skb) ?
TX_DESC_QSEL_HIGH : skb->priority;
else if (skb_get_queue_mapping(skb) <= IEEE80211_AC_BK)
qsel = skb->priority;
@@ -647,7 +593,7 @@ static int rtw_usb_tx_write(struct rtw_dev *rtwdev,
u8 *pkt_desc;
int ep;
- pkt_info->qsel = rtw_usb_tx_queue_mapping_to_qsel(rtwusb, skb);
+ pkt_info->qsel = rtw_usb_tx_queue_mapping_to_qsel(rtwdev, skb);
pkt_desc = skb_push(skb, chip->tx_pkt_desc_sz);
memset(pkt_desc, 0, chip->tx_pkt_desc_sz);
ep = qsel_to_ep(rtwusb, pkt_info->qsel);
@@ -1088,10 +1034,6 @@ static int rtw_usb_init_tx(struct rtw_dev *rtwdev)
struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
int i;
- spin_lock_init(&rtwusb->hiq_lock);
- rtwusb->hiq_budget = RTW_USB_HIQ_BUDGET_MAX;
- rtwusb->hiq_refill = jiffies;
-
rtwusb->txwq = create_singlethread_workqueue("rtw88_usb: tx wq");
if (!rtwusb->txwq) {
rtw_err(rtwdev, "failed to create TX work queue\n");
diff --git a/drivers/net/wireless/realtek/rtw88/usb.h b/drivers/net/wireless/realtek/rtw88/usb.h
index 94ff21dd0846..9b695b688b24 100644
--- a/drivers/net/wireless/realtek/rtw88/usb.h
+++ b/drivers/net/wireless/realtek/rtw88/usb.h
@@ -75,11 +75,6 @@ struct rtw_usb {
u8 out_ep[RTW_USB_EP_MAX];
int qsel_to_ep[TX_DESC_QSEL_MAX];
- /* protects hiq_budget and hiq_refill */
- spinlock_t hiq_lock;
- u32 hiq_budget;
- unsigned long hiq_refill;
-
struct workqueue_struct *txwq, *rxwq;
struct sk_buff_head tx_queue[RTW_USB_EP_MAX];
--
2.53.0
next reply other threads:[~2026-10-21 12:43 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-21 12:43 Luka Gejak [this message]
2026-10-21 12:43 ` [PATCH rtw-next v2 2/2] wifi: rtw88: sdio: limit the high queue to DTIM delivery Luka Gejak
2026-10-22 2:24 ` Ping-Ke Shih
2026-10-22 4:30 ` Luka Gejak
2026-10-22 4:33 ` Ping-Ke Shih
2026-10-22 2:20 ` [PATCH rtw-next v2 1/2] wifi: rtw88: move the bmc high queue decision to tx.c Ping-Ke Shih
2026-10-22 5:11 ` Luka Gejak
2026-10-23 21:34 ` Luka Gejak
2026-10-25 2:49 ` Ping-Ke Shih
2026-10-25 8:26 ` Luka Gejak
2026-10-27 1:19 ` Ping-Ke Shih
2026-10-27 5:22 ` Luka Gejak
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=20261021124318.15993-1-luka.gejak@linux.dev \
--to=luka.gejak@linux.dev \
--cc=linux-wireless@vger.kernel.org \
--cc=pkshih@realtek.com \
/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.