linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH rtw-next v1 00/13] wifi: rtw89: Add support for USB devices
@ 2025-05-04 20:47 Bitterblue Smith
  2025-05-04 20:49 ` [PATCH rtw-next v1 01/13] wifi: rtw89: 8851b: Accept USB devices and load their MAC address Bitterblue Smith
                   ` (14 more replies)
  0 siblings, 15 replies; 47+ messages in thread
From: Bitterblue Smith @ 2025-05-04 20:47 UTC (permalink / raw)
  To: linux-wireless@vger.kernel.org; +Cc: Ping-Ke Shih

Add support for USB devices, starting with just RTL8851BU.
RTL8832BU/RTL8852BU can be supported easily later. RTL8832CU/RTL8852CU
can be supported as well, but it keeps losing the connection.

This is based on rtw88_usb and the official rtl8851bu driver
v1.19.10-70-g84e35c28d.20231019 from here:
https://github.com/fofajardo/rtl8851bu

I didn't test with any PCI devices.

Bitterblue Smith (13):
  wifi: rtw89: 8851b: Accept USB devices and load their MAC address
  wifi: rtw89: Get dle_mem via rtw89_hci_dle_mem()
  wifi: rtw89: Rename hfc_param_ini to hfc_param_ini_pcie
  wifi: rtw89: Add dle_mem_usb2 and dle_mem_usb3
  wifi: rtw89: Add hfc_param_ini_usb
  wifi: rtw89: Disable some power saving for USB
  wifi: rtw89: Add extra TX headroom for USB
  wifi: rtw89: Hide some errors when the device is unplugged
  wifi: rtw89: Fix rtw89_mac_power_switch() for USB
  wifi: rtw89: Add some definitions for USB
  wifi: rtw89: Add usb.{c,h}
  wifi: rtw89: Add rtw8851bu.c
  wifi: rtw89: Enable the new USB modules

 drivers/net/wireless/realtek/rtw89/Kconfig    |   14 +
 drivers/net/wireless/realtek/rtw89/Makefile   |    6 +
 drivers/net/wireless/realtek/rtw89/core.c     |    3 +
 drivers/net/wireless/realtek/rtw89/core.h     |   16 +-
 drivers/net/wireless/realtek/rtw89/mac.c      |   49 +-
 drivers/net/wireless/realtek/rtw89/mac.h      |    8 +
 drivers/net/wireless/realtek/rtw89/pci.c      |    8 +
 drivers/net/wireless/realtek/rtw89/phy.c      |    3 +-
 drivers/net/wireless/realtek/rtw89/ps.c       |    3 +
 drivers/net/wireless/realtek/rtw89/reg.h      |   30 +
 drivers/net/wireless/realtek/rtw89/rtw8851b.c |   91 +-
 .../net/wireless/realtek/rtw89/rtw8851bu.c    |   33 +
 drivers/net/wireless/realtek/rtw89/rtw8852a.c |    7 +-
 drivers/net/wireless/realtek/rtw89/rtw8852b.c |    7 +-
 .../net/wireless/realtek/rtw89/rtw8852bt.c    |    7 +-
 drivers/net/wireless/realtek/rtw89/rtw8852c.c |    7 +-
 drivers/net/wireless/realtek/rtw89/rtw8922a.c |    7 +-
 drivers/net/wireless/realtek/rtw89/txrx.h     |    1 +
 drivers/net/wireless/realtek/rtw89/usb.c      | 1030 +++++++++++++++++
 drivers/net/wireless/realtek/rtw89/usb.h      |   61 +
 20 files changed, 1359 insertions(+), 32 deletions(-)
 create mode 100644 drivers/net/wireless/realtek/rtw89/rtw8851bu.c
 create mode 100644 drivers/net/wireless/realtek/rtw89/usb.c
 create mode 100644 drivers/net/wireless/realtek/rtw89/usb.h

-- 
2.49.0


^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH rtw-next v1 01/13] wifi: rtw89: 8851b: Accept USB devices and load their MAC address
  2025-05-04 20:47 [PATCH rtw-next v1 00/13] wifi: rtw89: Add support for USB devices Bitterblue Smith
@ 2025-05-04 20:49 ` Bitterblue Smith
  2025-05-13  2:46   ` Ping-Ke Shih
  2025-05-04 20:49 ` [PATCH rtw-next v1 02/13] wifi: rtw89: Get dle_mem via rtw89_hci_dle_mem() Bitterblue Smith
                   ` (13 subsequent siblings)
  14 siblings, 1 reply; 47+ messages in thread
From: Bitterblue Smith @ 2025-05-04 20:49 UTC (permalink / raw)
  To: linux-wireless@vger.kernel.org; +Cc: Ping-Ke Shih

Make rtw8851b_read_efuse() accept USB devices and load the MAC address
from the correct offset.

Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
---
 drivers/net/wireless/realtek/rtw89/rtw8851b.c | 16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c
index 174b90661037..8d774bd75edb 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8851b.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c
@@ -461,14 +461,6 @@ static int rtw8851b_pwr_off_func(struct rtw89_dev *rtwdev)
 	return 0;
 }
 
-static void rtw8851b_efuse_parsing(struct rtw89_efuse *efuse,
-				   struct rtw8851b_efuse *map)
-{
-	ether_addr_copy(efuse->addr, map->e.mac_addr);
-	efuse->rfe_type = map->rfe_type;
-	efuse->xtal_cap = map->xtal_k;
-}
-
 static void rtw8851b_efuse_parsing_tssi(struct rtw89_dev *rtwdev,
 					struct rtw8851b_efuse *map)
 {
@@ -549,12 +541,18 @@ static int rtw8851b_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map,
 
 	switch (rtwdev->hci.type) {
 	case RTW89_HCI_TYPE_PCIE:
-		rtw8851b_efuse_parsing(efuse, map);
+		ether_addr_copy(efuse->addr, map->e.mac_addr);
+		break;
+	case RTW89_HCI_TYPE_USB:
+		ether_addr_copy(efuse->addr, map->u.mac_addr);
 		break;
 	default:
 		return -EOPNOTSUPP;
 	}
 
+	efuse->rfe_type = map->rfe_type;
+	efuse->xtal_cap = map->xtal_k;
+
 	rtw89_info(rtwdev, "chip rfe_type is %d\n", efuse->rfe_type);
 
 	return 0;
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH rtw-next v1 02/13] wifi: rtw89: Get dle_mem via rtw89_hci_dle_mem()
  2025-05-04 20:47 [PATCH rtw-next v1 00/13] wifi: rtw89: Add support for USB devices Bitterblue Smith
  2025-05-04 20:49 ` [PATCH rtw-next v1 01/13] wifi: rtw89: 8851b: Accept USB devices and load their MAC address Bitterblue Smith
@ 2025-05-04 20:49 ` Bitterblue Smith
  2025-05-13  2:51   ` Ping-Ke Shih
  2025-05-14  0:56   ` Ping-Ke Shih
  2025-05-04 20:49 ` [PATCH rtw-next v1 03/13] wifi: rtw89: Rename hfc_param_ini to hfc_param_ini_pcie Bitterblue Smith
                   ` (12 subsequent siblings)
  14 siblings, 2 replies; 47+ messages in thread
From: Bitterblue Smith @ 2025-05-04 20:49 UTC (permalink / raw)
  To: linux-wireless@vger.kernel.org; +Cc: Ping-Ke Shih

Don't access dle_mem in get_dle_mem_cfg() directly. USB 2, USB 3, and
SDIO will need different sets of values.

Rename dle_mem in struct rtw89_chip_info to dle_mem_pcie and get it
via rtw89_hci_dle_mem() and rtw89_pci_ops_dle_mem().

Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
---
 drivers/net/wireless/realtek/rtw89/core.h      | 10 +++++++++-
 drivers/net/wireless/realtek/rtw89/mac.c       |  2 +-
 drivers/net/wireless/realtek/rtw89/pci.c       |  8 ++++++++
 drivers/net/wireless/realtek/rtw89/rtw8851b.c  |  2 +-
 drivers/net/wireless/realtek/rtw89/rtw8852a.c  |  2 +-
 drivers/net/wireless/realtek/rtw89/rtw8852b.c  |  2 +-
 drivers/net/wireless/realtek/rtw89/rtw8852bt.c |  2 +-
 drivers/net/wireless/realtek/rtw89/rtw8852c.c  |  2 +-
 drivers/net/wireless/realtek/rtw89/rtw8922a.c  |  2 +-
 9 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index be1259cfa712..afcf0353a625 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -3579,6 +3579,8 @@ struct rtw89_hci_ops {
 	void (*disable_intr)(struct rtw89_dev *rtwdev);
 	void (*enable_intr)(struct rtw89_dev *rtwdev);
 	int (*rst_bdram)(struct rtw89_dev *rtwdev);
+	const struct rtw89_dle_mem *(*dle_mem)(struct rtw89_dev *rtwdev,
+					       u8 qta_mode);
 };
 
 struct rtw89_hci_info {
@@ -4271,7 +4273,7 @@ struct rtw89_chip_info {
 	bool dis_2g_40m_ul_ofdma;
 	u32 rsvd_ple_ofst;
 	const struct rtw89_hfc_param_ini *hfc_param_ini;
-	const struct rtw89_dle_mem *dle_mem;
+	const struct rtw89_dle_mem *dle_mem_pcie;
 	u8 wde_qempty_acq_grpnum;
 	u8 wde_qempty_mgq_grpsel;
 	u32 rf_base_addr[2];
@@ -6146,6 +6148,12 @@ static inline void rtw89_hci_clear(struct rtw89_dev *rtwdev, struct pci_dev *pde
 		rtwdev->hci.ops->clear(rtwdev, pdev);
 }
 
+static inline const
+struct rtw89_dle_mem *rtw89_hci_dle_mem(struct rtw89_dev *rtwdev, u8 qta_mode)
+{
+	return rtwdev->hci.ops->dle_mem(rtwdev, qta_mode);
+}
+
 static inline
 struct rtw89_tx_skb_data *RTW89_TX_SKB_CB(struct sk_buff *skb)
 {
diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
index 592fbb6d2728..77d35db3e133 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.c
+++ b/drivers/net/wireless/realtek/rtw89/mac.c
@@ -1719,7 +1719,7 @@ static const struct rtw89_dle_mem *get_dle_mem_cfg(struct rtw89_dev *rtwdev,
 	struct rtw89_mac_info *mac = &rtwdev->mac;
 	const struct rtw89_dle_mem *cfg;
 
-	cfg = &rtwdev->chip->dle_mem[mode];
+	cfg = rtw89_hci_dle_mem(rtwdev, mode);
 	if (!cfg)
 		return NULL;
 
diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c
index c2fe5a898dc7..1dec603012ba 100644
--- a/drivers/net/wireless/realtek/rtw89/pci.c
+++ b/drivers/net/wireless/realtek/rtw89/pci.c
@@ -4341,6 +4341,13 @@ static int __maybe_unused rtw89_pci_resume(struct device *dev)
 SIMPLE_DEV_PM_OPS(rtw89_pm_ops, rtw89_pci_suspend, rtw89_pci_resume);
 EXPORT_SYMBOL(rtw89_pm_ops);
 
+static const
+struct rtw89_dle_mem *rtw89_pci_ops_dle_mem(struct rtw89_dev *rtwdev,
+					    u8 qta_mode)
+{
+	return &rtwdev->chip->dle_mem_pcie[qta_mode];
+}
+
 const struct rtw89_pci_gen_def rtw89_pci_gen_ax = {
 	.isr_rdu = B_AX_RDU_INT,
 	.isr_halt_c2h = B_AX_HALT_C2H_INT_EN,
@@ -4413,6 +4420,7 @@ static const struct rtw89_hci_ops rtw89_pci_ops = {
 	.disable_intr	= rtw89_pci_disable_intr_lock,
 	.enable_intr	= rtw89_pci_enable_intr_lock,
 	.rst_bdram	= rtw89_pci_reset_bdram,
+	.dle_mem	= rtw89_pci_ops_dle_mem,
 };
 
 int rtw89_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c
index 8d774bd75edb..1295718b8fdc 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8851b.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c
@@ -2465,7 +2465,7 @@ const struct rtw89_chip_info rtw8851b_chip_info = {
 	.dis_2g_40m_ul_ofdma	= true,
 	.rsvd_ple_ofst		= 0x2f800,
 	.hfc_param_ini		= rtw8851b_hfc_param_ini_pcie,
-	.dle_mem		= rtw8851b_dle_mem_pcie,
+	.dle_mem_pcie		= rtw8851b_dle_mem_pcie,
 	.wde_qempty_acq_grpnum	= 4,
 	.wde_qempty_mgq_grpsel	= 4,
 	.rf_base_addr		= {0xe000},
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
index 408c2f7b3eec..5e9e2fc09458 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
@@ -2184,7 +2184,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
 	.dis_2g_40m_ul_ofdma	= true,
 	.rsvd_ple_ofst		= 0x6f800,
 	.hfc_param_ini		= rtw8852a_hfc_param_ini_pcie,
-	.dle_mem		= rtw8852a_dle_mem_pcie,
+	.dle_mem_pcie		= rtw8852a_dle_mem_pcie,
 	.wde_qempty_acq_grpnum	= 16,
 	.wde_qempty_mgq_grpsel	= 16,
 	.rf_base_addr		= {0xc000, 0xd000},
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c
index dec736a07c54..badaea9d4cb8 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c
@@ -820,7 +820,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = {
 	.dis_2g_40m_ul_ofdma	= true,
 	.rsvd_ple_ofst		= 0x2f800,
 	.hfc_param_ini		= rtw8852b_hfc_param_ini_pcie,
-	.dle_mem		= rtw8852b_dle_mem_pcie,
+	.dle_mem_pcie		= rtw8852b_dle_mem_pcie,
 	.wde_qempty_acq_grpnum	= 4,
 	.wde_qempty_mgq_grpsel	= 4,
 	.rf_base_addr		= {0xe000, 0xf000},
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c
index 3aaf70e32652..74619361e29b 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c
@@ -754,7 +754,7 @@ const struct rtw89_chip_info rtw8852bt_chip_info = {
 	.dis_2g_40m_ul_ofdma	= true,
 	.rsvd_ple_ofst		= 0x6f800,
 	.hfc_param_ini		= rtw8852bt_hfc_param_ini_pcie,
-	.dle_mem		= rtw8852bt_dle_mem_pcie,
+	.dle_mem_pcie		= rtw8852bt_dle_mem_pcie,
 	.wde_qempty_acq_grpnum	= 4,
 	.wde_qempty_mgq_grpsel	= 4,
 	.rf_base_addr		= {0xe000, 0xf000},
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
index 9a2235f28e24..8b049c3ace93 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
@@ -3004,7 +3004,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
 	.dis_2g_40m_ul_ofdma	= false,
 	.rsvd_ple_ofst		= 0x6f800,
 	.hfc_param_ini		= rtw8852c_hfc_param_ini_pcie,
-	.dle_mem		= rtw8852c_dle_mem_pcie,
+	.dle_mem_pcie		= rtw8852c_dle_mem_pcie,
 	.wde_qempty_acq_grpnum	= 16,
 	.wde_qempty_mgq_grpsel	= 16,
 	.rf_base_addr		= {0xe000, 0xf000},
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a.c b/drivers/net/wireless/realtek/rtw89/rtw8922a.c
index cc595cae53f5..505f45595dc8 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922a.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922a.c
@@ -2816,7 +2816,7 @@ const struct rtw89_chip_info rtw8922a_chip_info = {
 	.dis_2g_40m_ul_ofdma	= false,
 	.rsvd_ple_ofst		= 0x8f800,
 	.hfc_param_ini		= rtw8922a_hfc_param_ini_pcie,
-	.dle_mem		= rtw8922a_dle_mem_pcie,
+	.dle_mem_pcie		= rtw8922a_dle_mem_pcie,
 	.wde_qempty_acq_grpnum	= 4,
 	.wde_qempty_mgq_grpsel	= 4,
 	.rf_base_addr		= {0xe000, 0xf000},
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH rtw-next v1 03/13] wifi: rtw89: Rename hfc_param_ini to hfc_param_ini_pcie
  2025-05-04 20:47 [PATCH rtw-next v1 00/13] wifi: rtw89: Add support for USB devices Bitterblue Smith
  2025-05-04 20:49 ` [PATCH rtw-next v1 01/13] wifi: rtw89: 8851b: Accept USB devices and load their MAC address Bitterblue Smith
  2025-05-04 20:49 ` [PATCH rtw-next v1 02/13] wifi: rtw89: Get dle_mem via rtw89_hci_dle_mem() Bitterblue Smith
@ 2025-05-04 20:49 ` Bitterblue Smith
  2025-05-13  3:04   ` Ping-Ke Shih
  2025-05-04 20:50 ` [PATCH rtw-next v1 04/13] wifi: rtw89: Add dle_mem_usb2 and dle_mem_usb3 Bitterblue Smith
                   ` (11 subsequent siblings)
  14 siblings, 1 reply; 47+ messages in thread
From: Bitterblue Smith @ 2025-05-04 20:49 UTC (permalink / raw)
  To: linux-wireless@vger.kernel.org; +Cc: Ping-Ke Shih

Rename hfc_param_ini in struct rtw89_chip_info to hfc_param_ini_pcie.
USB and SDIO will need different sets of values.

Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
---
 drivers/net/wireless/realtek/rtw89/core.h      | 2 +-
 drivers/net/wireless/realtek/rtw89/mac.c       | 2 +-
 drivers/net/wireless/realtek/rtw89/rtw8851b.c  | 2 +-
 drivers/net/wireless/realtek/rtw89/rtw8852a.c  | 2 +-
 drivers/net/wireless/realtek/rtw89/rtw8852b.c  | 2 +-
 drivers/net/wireless/realtek/rtw89/rtw8852bt.c | 2 +-
 drivers/net/wireless/realtek/rtw89/rtw8852c.c  | 2 +-
 drivers/net/wireless/realtek/rtw89/rtw8922a.c  | 2 +-
 8 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index afcf0353a625..321de0f76026 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -4272,7 +4272,7 @@ struct rtw89_chip_info {
 	u16 max_amsdu_limit;
 	bool dis_2g_40m_ul_ofdma;
 	u32 rsvd_ple_ofst;
-	const struct rtw89_hfc_param_ini *hfc_param_ini;
+	const struct rtw89_hfc_param_ini *hfc_param_ini_pcie;
 	const struct rtw89_dle_mem *dle_mem_pcie;
 	u8 wde_qempty_acq_grpnum;
 	u8 wde_qempty_mgq_grpsel;
diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
index 77d35db3e133..a52de0af605e 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.c
+++ b/drivers/net/wireless/realtek/rtw89/mac.c
@@ -881,7 +881,7 @@ static int hfc_reset_param(struct rtw89_dev *rtwdev)
 
 	switch (rtwdev->hci.type) {
 	case RTW89_HCI_TYPE_PCIE:
-		param_ini = rtwdev->chip->hfc_param_ini[qta_mode];
+		param_ini = rtwdev->chip->hfc_param_ini_pcie[qta_mode];
 		param->en = 0;
 		break;
 	default:
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c
index 1295718b8fdc..8d5ee870617c 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8851b.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c
@@ -2464,7 +2464,7 @@ const struct rtw89_chip_info rtw8851b_chip_info = {
 	.max_amsdu_limit	= 3500,
 	.dis_2g_40m_ul_ofdma	= true,
 	.rsvd_ple_ofst		= 0x2f800,
-	.hfc_param_ini		= rtw8851b_hfc_param_ini_pcie,
+	.hfc_param_ini_pcie	= rtw8851b_hfc_param_ini_pcie,
 	.dle_mem_pcie		= rtw8851b_dle_mem_pcie,
 	.wde_qempty_acq_grpnum	= 4,
 	.wde_qempty_mgq_grpsel	= 4,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
index 5e9e2fc09458..efa944a66976 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
@@ -2183,7 +2183,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
 	.max_amsdu_limit	= 3500,
 	.dis_2g_40m_ul_ofdma	= true,
 	.rsvd_ple_ofst		= 0x6f800,
-	.hfc_param_ini		= rtw8852a_hfc_param_ini_pcie,
+	.hfc_param_ini_pcie	= rtw8852a_hfc_param_ini_pcie,
 	.dle_mem_pcie		= rtw8852a_dle_mem_pcie,
 	.wde_qempty_acq_grpnum	= 16,
 	.wde_qempty_mgq_grpsel	= 16,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c
index badaea9d4cb8..b157fb831479 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c
@@ -819,7 +819,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = {
 	.max_amsdu_limit	= 5000,
 	.dis_2g_40m_ul_ofdma	= true,
 	.rsvd_ple_ofst		= 0x2f800,
-	.hfc_param_ini		= rtw8852b_hfc_param_ini_pcie,
+	.hfc_param_ini_pcie	= rtw8852b_hfc_param_ini_pcie,
 	.dle_mem_pcie		= rtw8852b_dle_mem_pcie,
 	.wde_qempty_acq_grpnum	= 4,
 	.wde_qempty_mgq_grpsel	= 4,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c
index 74619361e29b..78abe49a6034 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c
@@ -753,7 +753,7 @@ const struct rtw89_chip_info rtw8852bt_chip_info = {
 	.max_amsdu_limit	= 5000,
 	.dis_2g_40m_ul_ofdma	= true,
 	.rsvd_ple_ofst		= 0x6f800,
-	.hfc_param_ini		= rtw8852bt_hfc_param_ini_pcie,
+	.hfc_param_ini_pcie	= rtw8852bt_hfc_param_ini_pcie,
 	.dle_mem_pcie		= rtw8852bt_dle_mem_pcie,
 	.wde_qempty_acq_grpnum	= 4,
 	.wde_qempty_mgq_grpsel	= 4,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
index 8b049c3ace93..cdabfe6acd72 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
@@ -3003,7 +3003,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
 	.max_amsdu_limit	= 8000,
 	.dis_2g_40m_ul_ofdma	= false,
 	.rsvd_ple_ofst		= 0x6f800,
-	.hfc_param_ini		= rtw8852c_hfc_param_ini_pcie,
+	.hfc_param_ini_pcie	= rtw8852c_hfc_param_ini_pcie,
 	.dle_mem_pcie		= rtw8852c_dle_mem_pcie,
 	.wde_qempty_acq_grpnum	= 16,
 	.wde_qempty_mgq_grpsel	= 16,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a.c b/drivers/net/wireless/realtek/rtw89/rtw8922a.c
index 505f45595dc8..0fce7219246d 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922a.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922a.c
@@ -2815,7 +2815,7 @@ const struct rtw89_chip_info rtw8922a_chip_info = {
 	.max_amsdu_limit	= 8000,
 	.dis_2g_40m_ul_ofdma	= false,
 	.rsvd_ple_ofst		= 0x8f800,
-	.hfc_param_ini		= rtw8922a_hfc_param_ini_pcie,
+	.hfc_param_ini_pcie	= rtw8922a_hfc_param_ini_pcie,
 	.dle_mem_pcie		= rtw8922a_dle_mem_pcie,
 	.wde_qempty_acq_grpnum	= 4,
 	.wde_qempty_mgq_grpsel	= 4,
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH rtw-next v1 04/13] wifi: rtw89: Add dle_mem_usb2 and dle_mem_usb3
  2025-05-04 20:47 [PATCH rtw-next v1 00/13] wifi: rtw89: Add support for USB devices Bitterblue Smith
                   ` (2 preceding siblings ...)
  2025-05-04 20:49 ` [PATCH rtw-next v1 03/13] wifi: rtw89: Rename hfc_param_ini to hfc_param_ini_pcie Bitterblue Smith
@ 2025-05-04 20:50 ` Bitterblue Smith
  2025-05-13  3:06   ` Ping-Ke Shih
  2025-05-04 20:51 ` [PATCH rtw-next v1 05/13] wifi: rtw89: Add hfc_param_ini_usb Bitterblue Smith
                   ` (10 subsequent siblings)
  14 siblings, 1 reply; 47+ messages in thread
From: Bitterblue Smith @ 2025-05-04 20:50 UTC (permalink / raw)
  To: linux-wireless@vger.kernel.org; +Cc: Ping-Ke Shih

Add new members dle_mem_usb2 and dle_mem_usb3 to struct rtw89_chip_info.
For now initialise them only for RTL8851B.

Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
---
 drivers/net/wireless/realtek/rtw89/core.h     |  2 ++
 drivers/net/wireless/realtek/rtw89/mac.c      | 15 ++++++++++
 drivers/net/wireless/realtek/rtw89/mac.h      |  8 ++++++
 drivers/net/wireless/realtek/rtw89/rtw8851b.c | 28 +++++++++++++++++++
 drivers/net/wireless/realtek/rtw89/rtw8852a.c |  2 ++
 drivers/net/wireless/realtek/rtw89/rtw8852b.c |  2 ++
 .../net/wireless/realtek/rtw89/rtw8852bt.c    |  2 ++
 drivers/net/wireless/realtek/rtw89/rtw8852c.c |  2 ++
 drivers/net/wireless/realtek/rtw89/rtw8922a.c |  2 ++
 9 files changed, 63 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 321de0f76026..335d2314699b 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -4274,6 +4274,8 @@ struct rtw89_chip_info {
 	u32 rsvd_ple_ofst;
 	const struct rtw89_hfc_param_ini *hfc_param_ini_pcie;
 	const struct rtw89_dle_mem *dle_mem_pcie;
+	const struct rtw89_dle_mem *dle_mem_usb2;
+	const struct rtw89_dle_mem *dle_mem_usb3;
 	u8 wde_qempty_acq_grpnum;
 	u8 wde_qempty_mgq_grpsel;
 	u32 rf_base_addr[2];
diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
index a52de0af605e..4a5d1a5926e9 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.c
+++ b/drivers/net/wireless/realtek/rtw89/mac.c
@@ -1646,6 +1646,8 @@ const struct rtw89_mac_size_set rtw89_mac_size = {
 	/* 8852C PCIE SCC */
 	.wde_size19 = {RTW89_WDE_PG_64, 3328, 0,},
 	.wde_size23 = {RTW89_WDE_PG_64, 1022, 2,},
+	/* 8852B USB2.0/USB3.0 SCC */
+	.wde_size25 = {RTW89_WDE_PG_64, 162, 94,},
 	/* PCIE */
 	.ple_size0 = {RTW89_PLE_PG_128, 1520, 16,},
 	.ple_size0_v1 = {RTW89_PLE_PG_128, 2688, 240, 212992,},
@@ -1661,6 +1663,10 @@ const struct rtw89_mac_size_set rtw89_mac_size = {
 	.ple_size18 = {RTW89_PLE_PG_128, 2544, 16,},
 	/* 8852C PCIE SCC */
 	.ple_size19 = {RTW89_PLE_PG_128, 1904, 16,},
+	/* 8852B USB2.0 SCC*/
+	.ple_size32 = {RTW89_PLE_PG_128, 620, 20,},
+	/* 8852B USB3.0 SCC*/
+	.ple_size33 = {RTW89_PLE_PG_128, 632, 8,},
 	/* PCIE 64 */
 	.wde_qt0 = {3792, 196, 0, 107,},
 	.wde_qt0_v1 = {3302, 6, 0, 20,},
@@ -1675,6 +1681,8 @@ const struct rtw89_mac_size_set rtw89_mac_size = {
 	/* 8852C PCIE SCC */
 	.wde_qt18 = {3228, 60, 0, 40,},
 	.wde_qt23 = {958, 48, 0, 16,},
+	/* 8852B USB2.0/USB3.0 SCC*/
+	.wde_qt25 = {152, 2, 0, 8,},
 	.ple_qt0 = {320, 320, 32, 16, 13, 13, 292, 292, 64, 18, 1, 4, 0,},
 	.ple_qt1 = {320, 320, 32, 16, 1316, 1316, 1595, 1595, 1367, 1321, 1, 1307, 0,},
 	/* PCIE SCC */
@@ -1698,6 +1706,13 @@ const struct rtw89_mac_size_set rtw89_mac_size = {
 	/* PCIE 64 */
 	.ple_qt58 = {147, 0, 16, 20, 157, 13, 229, 0, 172, 14, 24, 0,},
 	.ple_qt59 = {147, 0, 32, 20, 1860, 13, 2025, 0, 1879, 14, 24, 0,},
+	/* USB2.0 52B SCC */
+	.ple_qt72 = {130, 0, 16, 48, 4, 13, 322, 0, 32, 14, 8, 0, 0,},
+	/* USB2.0 52B 92K*/
+	.ple_qt73 = {130, 0, 32, 48, 37, 13, 355, 0, 65, 14, 24, 0, 0,},
+	/* USB3.0 52B 92K*/
+	.ple_qt74 = {286, 0, 16, 48, 4, 13, 178, 0, 32, 14, 8, 0, 0,},
+	.ple_qt75 = {286, 0, 32, 48, 37, 13, 211, 0, 65, 14, 24, 0, 0,},
 	/* 8852A PCIE WOW */
 	.ple_qt_52a_wow = {264, 0, 32, 20, 64, 13, 1005, 0, 64, 128, 120,},
 	/* 8852B PCIE WOW */
diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h
index 47d655fbf2ca..afef6228da30 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.h
+++ b/drivers/net/wireless/realtek/rtw89/mac.h
@@ -907,6 +907,7 @@ struct rtw89_mac_size_set {
 	const struct rtw89_dle_size wde_size18;
 	const struct rtw89_dle_size wde_size19;
 	const struct rtw89_dle_size wde_size23;
+	const struct rtw89_dle_size wde_size25;
 	const struct rtw89_dle_size ple_size0;
 	const struct rtw89_dle_size ple_size0_v1;
 	const struct rtw89_dle_size ple_size3_v1;
@@ -916,6 +917,8 @@ struct rtw89_mac_size_set {
 	const struct rtw89_dle_size ple_size9;
 	const struct rtw89_dle_size ple_size18;
 	const struct rtw89_dle_size ple_size19;
+	const struct rtw89_dle_size ple_size32;
+	const struct rtw89_dle_size ple_size33;
 	const struct rtw89_wde_quota wde_qt0;
 	const struct rtw89_wde_quota wde_qt0_v1;
 	const struct rtw89_wde_quota wde_qt4;
@@ -924,6 +927,7 @@ struct rtw89_mac_size_set {
 	const struct rtw89_wde_quota wde_qt17;
 	const struct rtw89_wde_quota wde_qt18;
 	const struct rtw89_wde_quota wde_qt23;
+	const struct rtw89_wde_quota wde_qt25;
 	const struct rtw89_ple_quota ple_qt0;
 	const struct rtw89_ple_quota ple_qt1;
 	const struct rtw89_ple_quota ple_qt4;
@@ -938,6 +942,10 @@ struct rtw89_mac_size_set {
 	const struct rtw89_ple_quota ple_qt57;
 	const struct rtw89_ple_quota ple_qt58;
 	const struct rtw89_ple_quota ple_qt59;
+	const struct rtw89_ple_quota ple_qt72;
+	const struct rtw89_ple_quota ple_qt73;
+	const struct rtw89_ple_quota ple_qt74;
+	const struct rtw89_ple_quota ple_qt75;
 	const struct rtw89_ple_quota ple_qt_52a_wow;
 	const struct rtw89_ple_quota ple_qt_52b_wow;
 	const struct rtw89_ple_quota ple_qt_52bt_wow;
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c
index 8d5ee870617c..d42bfdcac849 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8851b.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c
@@ -68,6 +68,32 @@ static const struct rtw89_dle_mem rtw8851b_dle_mem_pcie[] = {
 			       NULL},
 };
 
+static const struct rtw89_dle_mem rtw8851b_dle_mem_usb2[] = {
+	[RTW89_QTA_SCC] = {RTW89_QTA_SCC, &rtw89_mac_size.wde_size25,
+			   &rtw89_mac_size.ple_size32, &rtw89_mac_size.wde_qt25,
+			   &rtw89_mac_size.wde_qt25, &rtw89_mac_size.ple_qt72,
+			   &rtw89_mac_size.ple_qt73},
+	[RTW89_QTA_DLFW] = {RTW89_QTA_DLFW, &rtw89_mac_size.wde_size9,
+			    &rtw89_mac_size.ple_size8, &rtw89_mac_size.wde_qt4,
+			    &rtw89_mac_size.wde_qt4, &rtw89_mac_size.ple_qt13,
+			    &rtw89_mac_size.ple_qt13},
+	[RTW89_QTA_INVALID] = {RTW89_QTA_INVALID, NULL, NULL, NULL, NULL, NULL,
+			       NULL},
+};
+
+static const struct rtw89_dle_mem rtw8851b_dle_mem_usb3[] = {
+	[RTW89_QTA_SCC] = {RTW89_QTA_SCC, &rtw89_mac_size.wde_size25,
+			   &rtw89_mac_size.ple_size33, &rtw89_mac_size.wde_qt25,
+			   &rtw89_mac_size.wde_qt25, &rtw89_mac_size.ple_qt74,
+			   &rtw89_mac_size.ple_qt75},
+	[RTW89_QTA_DLFW] = {RTW89_QTA_DLFW, &rtw89_mac_size.wde_size9,
+			    &rtw89_mac_size.ple_size8, &rtw89_mac_size.wde_qt4,
+			    &rtw89_mac_size.wde_qt4, &rtw89_mac_size.ple_qt13,
+			    &rtw89_mac_size.ple_qt13},
+	[RTW89_QTA_INVALID] = {RTW89_QTA_INVALID, NULL, NULL, NULL, NULL, NULL,
+			       NULL},
+};
+
 static const struct rtw89_reg3_def rtw8851b_btc_preagc_en_defs[] = {
 	{0x46D0, GENMASK(1, 0), 0x3},
 	{0x4AD4, GENMASK(31, 0), 0xf},
@@ -2466,6 +2492,8 @@ const struct rtw89_chip_info rtw8851b_chip_info = {
 	.rsvd_ple_ofst		= 0x2f800,
 	.hfc_param_ini_pcie	= rtw8851b_hfc_param_ini_pcie,
 	.dle_mem_pcie		= rtw8851b_dle_mem_pcie,
+	.dle_mem_usb2		= rtw8851b_dle_mem_usb2,
+	.dle_mem_usb3		= rtw8851b_dle_mem_usb3,
 	.wde_qempty_acq_grpnum	= 4,
 	.wde_qempty_mgq_grpsel	= 4,
 	.rf_base_addr		= {0xe000},
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
index efa944a66976..b4be32ba8d37 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
@@ -2185,6 +2185,8 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
 	.rsvd_ple_ofst		= 0x6f800,
 	.hfc_param_ini_pcie	= rtw8852a_hfc_param_ini_pcie,
 	.dle_mem_pcie		= rtw8852a_dle_mem_pcie,
+	.dle_mem_usb2		= NULL,
+	.dle_mem_usb3		= NULL,
 	.wde_qempty_acq_grpnum	= 16,
 	.wde_qempty_mgq_grpsel	= 16,
 	.rf_base_addr		= {0xc000, 0xd000},
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c
index b157fb831479..cde7965860e8 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c
@@ -821,6 +821,8 @@ const struct rtw89_chip_info rtw8852b_chip_info = {
 	.rsvd_ple_ofst		= 0x2f800,
 	.hfc_param_ini_pcie	= rtw8852b_hfc_param_ini_pcie,
 	.dle_mem_pcie		= rtw8852b_dle_mem_pcie,
+	.dle_mem_usb2		= NULL,
+	.dle_mem_usb3		= NULL,
 	.wde_qempty_acq_grpnum	= 4,
 	.wde_qempty_mgq_grpsel	= 4,
 	.rf_base_addr		= {0xe000, 0xf000},
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c
index 78abe49a6034..35624f17de6d 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c
@@ -755,6 +755,8 @@ const struct rtw89_chip_info rtw8852bt_chip_info = {
 	.rsvd_ple_ofst		= 0x6f800,
 	.hfc_param_ini_pcie	= rtw8852bt_hfc_param_ini_pcie,
 	.dle_mem_pcie		= rtw8852bt_dle_mem_pcie,
+	.dle_mem_usb2		= NULL,
+	.dle_mem_usb3		= NULL,
 	.wde_qempty_acq_grpnum	= 4,
 	.wde_qempty_mgq_grpsel	= 4,
 	.rf_base_addr		= {0xe000, 0xf000},
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
index cdabfe6acd72..f96bc3036578 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
@@ -3005,6 +3005,8 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
 	.rsvd_ple_ofst		= 0x6f800,
 	.hfc_param_ini_pcie	= rtw8852c_hfc_param_ini_pcie,
 	.dle_mem_pcie		= rtw8852c_dle_mem_pcie,
+	.dle_mem_usb2		= NULL,
+	.dle_mem_usb3		= NULL,
 	.wde_qempty_acq_grpnum	= 16,
 	.wde_qempty_mgq_grpsel	= 16,
 	.rf_base_addr		= {0xe000, 0xf000},
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a.c b/drivers/net/wireless/realtek/rtw89/rtw8922a.c
index 0fce7219246d..ee2a664a7cce 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922a.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922a.c
@@ -2817,6 +2817,8 @@ const struct rtw89_chip_info rtw8922a_chip_info = {
 	.rsvd_ple_ofst		= 0x8f800,
 	.hfc_param_ini_pcie	= rtw8922a_hfc_param_ini_pcie,
 	.dle_mem_pcie		= rtw8922a_dle_mem_pcie,
+	.dle_mem_usb2		= NULL,
+	.dle_mem_usb3		= NULL,
 	.wde_qempty_acq_grpnum	= 4,
 	.wde_qempty_mgq_grpsel	= 4,
 	.rf_base_addr		= {0xe000, 0xf000},
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH rtw-next v1 05/13] wifi: rtw89: Add hfc_param_ini_usb
  2025-05-04 20:47 [PATCH rtw-next v1 00/13] wifi: rtw89: Add support for USB devices Bitterblue Smith
                   ` (3 preceding siblings ...)
  2025-05-04 20:50 ` [PATCH rtw-next v1 04/13] wifi: rtw89: Add dle_mem_usb2 and dle_mem_usb3 Bitterblue Smith
@ 2025-05-04 20:51 ` Bitterblue Smith
  2025-05-13  3:12   ` Ping-Ke Shih
  2025-05-04 20:51 ` [PATCH rtw-next v1 06/13] wifi: rtw89: Disable some power saving for USB Bitterblue Smith
                   ` (9 subsequent siblings)
  14 siblings, 1 reply; 47+ messages in thread
From: Bitterblue Smith @ 2025-05-04 20:51 UTC (permalink / raw)
  To: linux-wireless@vger.kernel.org; +Cc: Ping-Ke Shih

Add hfc_param_ini_usb to struct rtw89_chip_info. For now initialise it
only for RTL8851B.

Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
---
 drivers/net/wireless/realtek/rtw89/core.h     |  1 +
 drivers/net/wireless/realtek/rtw89/mac.c      |  6 ++-
 drivers/net/wireless/realtek/rtw89/rtw8851b.c | 43 +++++++++++++++++++
 drivers/net/wireless/realtek/rtw89/rtw8852a.c |  1 +
 drivers/net/wireless/realtek/rtw89/rtw8852b.c |  1 +
 .../net/wireless/realtek/rtw89/rtw8852bt.c    |  1 +
 drivers/net/wireless/realtek/rtw89/rtw8852c.c |  1 +
 drivers/net/wireless/realtek/rtw89/rtw8922a.c |  1 +
 8 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 335d2314699b..f17f046e773f 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -4273,6 +4273,7 @@ struct rtw89_chip_info {
 	bool dis_2g_40m_ul_ofdma;
 	u32 rsvd_ple_ofst;
 	const struct rtw89_hfc_param_ini *hfc_param_ini_pcie;
+	const struct rtw89_hfc_param_ini *hfc_param_ini_usb;
 	const struct rtw89_dle_mem *dle_mem_pcie;
 	const struct rtw89_dle_mem *dle_mem_usb2;
 	const struct rtw89_dle_mem *dle_mem_usb3;
diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
index 4a5d1a5926e9..a316864ad137 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.c
+++ b/drivers/net/wireless/realtek/rtw89/mac.c
@@ -882,12 +882,16 @@ static int hfc_reset_param(struct rtw89_dev *rtwdev)
 	switch (rtwdev->hci.type) {
 	case RTW89_HCI_TYPE_PCIE:
 		param_ini = rtwdev->chip->hfc_param_ini_pcie[qta_mode];
-		param->en = 0;
+		break;
+	case RTW89_HCI_TYPE_USB:
+		param_ini = rtwdev->chip->hfc_param_ini_usb[qta_mode];
 		break;
 	default:
 		return -EINVAL;
 	}
 
+	param->en = 0;
+
 	if (param_ini.pub_cfg)
 		param->pub_cfg = *param_ini.pub_cfg;
 
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c
index d42bfdcac849..35417cdde8d5 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8851b.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c
@@ -51,6 +51,48 @@ static const struct rtw89_hfc_param_ini rtw8851b_hfc_param_ini_pcie[] = {
 	[RTW89_QTA_INVALID] = {NULL},
 };
 
+static const struct rtw89_hfc_ch_cfg rtw8851b_hfc_chcfg_usb[] = {
+	{18, 152, grp_0}, /* ACH 0 */
+	{18, 152, grp_0}, /* ACH 1 */
+	{18, 152, grp_0}, /* ACH 2 */
+	{18, 152, grp_0}, /* ACH 3 */
+	{0, 0, grp_0}, /* ACH 4 */
+	{0, 0, grp_0}, /* ACH 5 */
+	{0, 0, grp_0}, /* ACH 6 */
+	{0, 0, grp_0}, /* ACH 7 */
+	{18, 152, grp_0}, /* B0MGQ */
+	{18, 152, grp_0}, /* B0HIQ */
+	{0, 0, grp_0}, /* B1MGQ */
+	{0, 0, grp_0}, /* B1HIQ */
+	{0, 0, 0} /* FWCMDQ */
+};
+
+static const struct rtw89_hfc_pub_cfg rtw8851b_hfc_pubcfg_usb = {
+	152, /* Group 0 */
+	0, /* Group 1 */
+	152, /* Public Max */
+	0 /* WP threshold */
+};
+
+static const struct rtw89_hfc_prec_cfg rtw8851b_hfc_preccfg_usb = {
+	9, /* CH 0-11 pre-cost */
+	32, /* H2C pre-cost */
+	64, /* WP CH 0-7 pre-cost */
+	24, /* WP CH 8-11 pre-cost */
+	1, /* CH 0-11 full condition */
+	1, /* H2C full condition */
+	1, /* WP CH 0-7 full condition */
+	1, /* WP CH 8-11 full condition */
+};
+
+static const struct rtw89_hfc_param_ini rtw8851b_hfc_param_ini_usb[] = {
+	[RTW89_QTA_SCC] = {rtw8851b_hfc_chcfg_usb, &rtw8851b_hfc_pubcfg_usb,
+			   &rtw8851b_hfc_preccfg_usb, RTW89_HCIFC_STF},
+	[RTW89_QTA_DLFW] = {NULL, NULL,
+			   &rtw8851b_hfc_preccfg_usb, RTW89_HCIFC_STF},
+	[RTW89_QTA_INVALID] = {NULL},
+};
+
 static const struct rtw89_dle_mem rtw8851b_dle_mem_pcie[] = {
 	[RTW89_QTA_SCC] = {RTW89_QTA_SCC, &rtw89_mac_size.wde_size6,
 			   &rtw89_mac_size.ple_size6, &rtw89_mac_size.wde_qt6,
@@ -2491,6 +2533,7 @@ const struct rtw89_chip_info rtw8851b_chip_info = {
 	.dis_2g_40m_ul_ofdma	= true,
 	.rsvd_ple_ofst		= 0x2f800,
 	.hfc_param_ini_pcie	= rtw8851b_hfc_param_ini_pcie,
+	.hfc_param_ini_usb	= rtw8851b_hfc_param_ini_usb,
 	.dle_mem_pcie		= rtw8851b_dle_mem_pcie,
 	.dle_mem_usb2		= rtw8851b_dle_mem_usb2,
 	.dle_mem_usb3		= rtw8851b_dle_mem_usb3,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
index b4be32ba8d37..9d0cb83d15a0 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
@@ -2184,6 +2184,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
 	.dis_2g_40m_ul_ofdma	= true,
 	.rsvd_ple_ofst		= 0x6f800,
 	.hfc_param_ini_pcie	= rtw8852a_hfc_param_ini_pcie,
+	.hfc_param_ini_usb	= NULL,
 	.dle_mem_pcie		= rtw8852a_dle_mem_pcie,
 	.dle_mem_usb2		= NULL,
 	.dle_mem_usb3		= NULL,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c
index cde7965860e8..9349d1a34bf6 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c
@@ -820,6 +820,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = {
 	.dis_2g_40m_ul_ofdma	= true,
 	.rsvd_ple_ofst		= 0x2f800,
 	.hfc_param_ini_pcie	= rtw8852b_hfc_param_ini_pcie,
+	.hfc_param_ini_usb	= NULL,
 	.dle_mem_pcie		= rtw8852b_dle_mem_pcie,
 	.dle_mem_usb2		= NULL,
 	.dle_mem_usb3		= NULL,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c
index 35624f17de6d..e32c6a1a25a8 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c
@@ -754,6 +754,7 @@ const struct rtw89_chip_info rtw8852bt_chip_info = {
 	.dis_2g_40m_ul_ofdma	= true,
 	.rsvd_ple_ofst		= 0x6f800,
 	.hfc_param_ini_pcie	= rtw8852bt_hfc_param_ini_pcie,
+	.hfc_param_ini_usb	= NULL,
 	.dle_mem_pcie		= rtw8852bt_dle_mem_pcie,
 	.dle_mem_usb2		= NULL,
 	.dle_mem_usb3		= NULL,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
index f96bc3036578..edbfca5bee3f 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
@@ -3004,6 +3004,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
 	.dis_2g_40m_ul_ofdma	= false,
 	.rsvd_ple_ofst		= 0x6f800,
 	.hfc_param_ini_pcie	= rtw8852c_hfc_param_ini_pcie,
+	.hfc_param_ini_usb	= NULL,
 	.dle_mem_pcie		= rtw8852c_dle_mem_pcie,
 	.dle_mem_usb2		= NULL,
 	.dle_mem_usb3		= NULL,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a.c b/drivers/net/wireless/realtek/rtw89/rtw8922a.c
index ee2a664a7cce..59e7e7a4d829 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922a.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922a.c
@@ -2816,6 +2816,7 @@ const struct rtw89_chip_info rtw8922a_chip_info = {
 	.dis_2g_40m_ul_ofdma	= false,
 	.rsvd_ple_ofst		= 0x8f800,
 	.hfc_param_ini_pcie	= rtw8922a_hfc_param_ini_pcie,
+	.hfc_param_ini_usb	= NULL,
 	.dle_mem_pcie		= rtw8922a_dle_mem_pcie,
 	.dle_mem_usb2		= NULL,
 	.dle_mem_usb3		= NULL,
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH rtw-next v1 06/13] wifi: rtw89: Disable some power saving for USB
  2025-05-04 20:47 [PATCH rtw-next v1 00/13] wifi: rtw89: Add support for USB devices Bitterblue Smith
                   ` (4 preceding siblings ...)
  2025-05-04 20:51 ` [PATCH rtw-next v1 05/13] wifi: rtw89: Add hfc_param_ini_usb Bitterblue Smith
@ 2025-05-04 20:51 ` Bitterblue Smith
  2025-05-13  3:27   ` Ping-Ke Shih
  2025-05-04 20:51 ` [PATCH rtw-next v1 07/13] wifi: rtw89: Add extra TX headroom " Bitterblue Smith
                   ` (8 subsequent siblings)
  14 siblings, 1 reply; 47+ messages in thread
From: Bitterblue Smith @ 2025-05-04 20:51 UTC (permalink / raw)
  To: linux-wireless@vger.kernel.org; +Cc: Ping-Ke Shih

Disable rtw89_ps_power_mode_change() and rtw89_mac_send_rpwm() for
USB because they are called in atomic context and accessing hardware
registers results in "scheduling while atomic" errors.

Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
---
 drivers/net/wireless/realtek/rtw89/mac.c | 3 +++
 drivers/net/wireless/realtek/rtw89/ps.c  | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
index a316864ad137..1a03355b340f 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.c
+++ b/drivers/net/wireless/realtek/rtw89/mac.c
@@ -1338,6 +1338,9 @@ static void rtw89_mac_send_rpwm(struct rtw89_dev *rtwdev,
 {
 	u16 request;
 
+	if (rtwdev->hci.type == RTW89_HCI_TYPE_USB)
+		return;
+
 	spin_lock_bh(&rtwdev->rpwm_lock);
 
 	request = rtw89_read16(rtwdev, R_AX_RPWM);
diff --git a/drivers/net/wireless/realtek/rtw89/ps.c b/drivers/net/wireless/realtek/rtw89/ps.c
index ac46a7baa00d..edff9f8e1016 100644
--- a/drivers/net/wireless/realtek/rtw89/ps.c
+++ b/drivers/net/wireless/realtek/rtw89/ps.c
@@ -56,6 +56,9 @@ static void rtw89_ps_power_mode_change_with_hci(struct rtw89_dev *rtwdev,
 
 static void rtw89_ps_power_mode_change(struct rtw89_dev *rtwdev, bool enter)
 {
+	if (rtwdev->hci.type == RTW89_HCI_TYPE_USB)
+		return;
+
 	if (rtwdev->chip->low_power_hci_modes & BIT(rtwdev->ps_mode) &&
 	    !test_bit(RTW89_FLAG_WOWLAN, rtwdev->flags))
 		rtw89_ps_power_mode_change_with_hci(rtwdev, enter);
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH rtw-next v1 07/13] wifi: rtw89: Add extra TX headroom for USB
  2025-05-04 20:47 [PATCH rtw-next v1 00/13] wifi: rtw89: Add support for USB devices Bitterblue Smith
                   ` (5 preceding siblings ...)
  2025-05-04 20:51 ` [PATCH rtw-next v1 06/13] wifi: rtw89: Disable some power saving for USB Bitterblue Smith
@ 2025-05-04 20:51 ` Bitterblue Smith
  2025-05-13  3:28   ` Ping-Ke Shih
  2025-05-04 20:52 ` [PATCH rtw-next v1 08/13] wifi: rtw89: Hide some errors when the device is unplugged Bitterblue Smith
                   ` (7 subsequent siblings)
  14 siblings, 1 reply; 47+ messages in thread
From: Bitterblue Smith @ 2025-05-04 20:51 UTC (permalink / raw)
  To: linux-wireless@vger.kernel.org; +Cc: Ping-Ke Shih

In the case of USB the TX descriptor is transmitted in the same buffer
as the 802.11 frame, so add the required headroom.

Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
---
 drivers/net/wireless/realtek/rtw89/core.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
index a6e67e22349e..0161721bb0e8 100644
--- a/drivers/net/wireless/realtek/rtw89/core.c
+++ b/drivers/net/wireless/realtek/rtw89/core.c
@@ -5251,6 +5251,9 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev)
 	int ret;
 	int tx_headroom = IEEE80211_HT_CTL_LEN;
 
+	if (rtwdev->hci.type == RTW89_HCI_TYPE_USB)
+		tx_headroom += chip->txwd_body_size + chip->txwd_info_size;
+
 	hw->vif_data_size = struct_size_t(struct rtw89_vif, links_inst, n);
 	hw->sta_data_size = struct_size_t(struct rtw89_sta, links_inst, n);
 	hw->txq_data_size = sizeof(struct rtw89_txq);
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH rtw-next v1 08/13] wifi: rtw89: Hide some errors when the device is unplugged
  2025-05-04 20:47 [PATCH rtw-next v1 00/13] wifi: rtw89: Add support for USB devices Bitterblue Smith
                   ` (6 preceding siblings ...)
  2025-05-04 20:51 ` [PATCH rtw-next v1 07/13] wifi: rtw89: Add extra TX headroom " Bitterblue Smith
@ 2025-05-04 20:52 ` Bitterblue Smith
  2025-05-13  3:43   ` Ping-Ke Shih
  2025-05-04 20:52 ` [PATCH rtw-next v1 09/13] wifi: rtw89: Fix rtw89_mac_power_switch() for USB Bitterblue Smith
                   ` (6 subsequent siblings)
  14 siblings, 1 reply; 47+ messages in thread
From: Bitterblue Smith @ 2025-05-04 20:52 UTC (permalink / raw)
  To: linux-wireless@vger.kernel.org; +Cc: Ping-Ke Shih

A few unnecessary error messages are printed when the device is
unplugged. "read swsi busy" in particular can appear ~1000 times when
RTL8851BU is unplugged.

Add a new flag RTW89_FLAG_UNPLUGGED and print some error messages only
when this flag is not set. The new USB driver will set the flag when
the device is unplugged.

Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
---
 drivers/net/wireless/realtek/rtw89/core.h |  1 +
 drivers/net/wireless/realtek/rtw89/mac.c  | 13 ++++++++-----
 drivers/net/wireless/realtek/rtw89/phy.c  |  3 ++-
 3 files changed, 11 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index f17f046e773f..015eb38a5a14 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -4895,6 +4895,7 @@ enum rtw89_flags {
 	RTW89_FLAG_FORBIDDEN_TRACK_WROK,
 	RTW89_FLAG_CHANGING_INTERFACE,
 	RTW89_FLAG_HW_RFKILL_STATE,
+	RTW89_FLAG_UNPLUGGED,
 
 	NUM_OF_RTW89_FLAGS,
 };
diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
index 1a03355b340f..99f01fff90fe 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.c
+++ b/drivers/net/wireless/realtek/rtw89/mac.c
@@ -88,7 +88,7 @@ int rtw89_mac_write_lte(struct rtw89_dev *rtwdev, const u32 offset, u32 val)
 
 	ret = read_poll_timeout(rtw89_read8, lte_ctrl, (lte_ctrl & BIT(5)) != 0,
 				50, 50000, false, rtwdev, R_AX_LTE_CTRL + 3);
-	if (ret)
+	if (ret && !test_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags))
 		rtw89_err(rtwdev, "[ERR]lte not ready(W)\n");
 
 	rtw89_write32(rtwdev, R_AX_LTE_WDATA, val);
@@ -104,7 +104,7 @@ int rtw89_mac_read_lte(struct rtw89_dev *rtwdev, const u32 offset, u32 *val)
 
 	ret = read_poll_timeout(rtw89_read8, lte_ctrl, (lte_ctrl & BIT(5)) != 0,
 				50, 50000, false, rtwdev, R_AX_LTE_CTRL + 3);
-	if (ret)
+	if (ret && !test_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags))
 		rtw89_err(rtwdev, "[ERR]lte not ready(W)\n");
 
 	rtw89_write32(rtwdev, R_AX_LTE_CTRL, 0x800F0000 | offset);
@@ -5842,13 +5842,15 @@ int rtw89_mac_coex_init(struct rtw89_dev *rtwdev, const struct rtw89_mac_ax_coex
 
 	ret = rtw89_mac_read_lte(rtwdev, R_AX_LTE_SW_CFG_2, &val32);
 	if (ret) {
-		rtw89_err(rtwdev, "Read R_AX_LTE_SW_CFG_2 fail!\n");
+		if (!test_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags))
+			rtw89_err(rtwdev, "Read R_AX_LTE_SW_CFG_2 fail!\n");
 		return ret;
 	}
 	val32 = val32 & B_AX_WL_RX_CTRL;
 	ret = rtw89_mac_write_lte(rtwdev, R_AX_LTE_SW_CFG_2, val32);
 	if (ret) {
-		rtw89_err(rtwdev, "Write R_AX_LTE_SW_CFG_2 fail!\n");
+		if (!test_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags))
+			rtw89_err(rtwdev, "Write R_AX_LTE_SW_CFG_2 fail!\n");
 		return ret;
 	}
 
@@ -5972,7 +5974,8 @@ int rtw89_mac_cfg_gnt(struct rtw89_dev *rtwdev,
 
 	ret = rtw89_mac_write_lte(rtwdev, R_AX_LTE_SW_CFG_1, val);
 	if (ret) {
-		rtw89_err(rtwdev, "Write LTE fail!\n");
+		if (!test_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags))
+			rtw89_err(rtwdev, "Write LTE fail!\n");
 		return ret;
 	}
 
diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c
index 270f40e44c0b..dfff46b92730 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.c
+++ b/drivers/net/wireless/realtek/rtw89/phy.c
@@ -895,7 +895,8 @@ static u32 rtw89_phy_read_rf_a(struct rtw89_dev *rtwdev,
 				       30, false, rtwdev, R_SWSI_V1,
 				       B_SWSI_R_DATA_DONE_V1);
 	if (ret) {
-		rtw89_err(rtwdev, "read swsi busy\n");
+		if (!test_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags))
+			rtw89_err(rtwdev, "read swsi busy\n");
 		return INV_RF_DATA;
 	}
 
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH rtw-next v1 09/13] wifi: rtw89: Fix rtw89_mac_power_switch() for USB
  2025-05-04 20:47 [PATCH rtw-next v1 00/13] wifi: rtw89: Add support for USB devices Bitterblue Smith
                   ` (7 preceding siblings ...)
  2025-05-04 20:52 ` [PATCH rtw-next v1 08/13] wifi: rtw89: Hide some errors when the device is unplugged Bitterblue Smith
@ 2025-05-04 20:52 ` Bitterblue Smith
  2025-05-13  3:50   ` Ping-Ke Shih
  2025-05-04 20:53 ` [PATCH rtw-next v1 10/13] wifi: rtw89: Add some definitions " Bitterblue Smith
                   ` (5 subsequent siblings)
  14 siblings, 1 reply; 47+ messages in thread
From: Bitterblue Smith @ 2025-05-04 20:52 UTC (permalink / raw)
  To: linux-wireless@vger.kernel.org; +Cc: Ping-Ke Shih

Clear some bits in some registers in order to allow RTL8851BU to power
on. Also tested with RTL8832BU and RTL8832CU.

Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
---
 drivers/net/wireless/realtek/rtw89/mac.c | 8 ++++++++
 drivers/net/wireless/realtek/rtw89/reg.h | 1 +
 2 files changed, 9 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
index 99f01fff90fe..d3cf67dfabc9 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.c
+++ b/drivers/net/wireless/realtek/rtw89/mac.c
@@ -1458,6 +1458,14 @@ static int rtw89_mac_power_switch(struct rtw89_dev *rtwdev, bool on)
 	int ret;
 	u8 val;
 
+	if (rtwdev->hci.type == RTW89_HCI_TYPE_USB &&
+	    rtw89_read32_mask(rtwdev, R_AX_GPIO_MUXCFG, B_AX_BOOT_MODE)) {
+		rtw89_write32_clr(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APFN_ONMAC);
+		rtw89_write32_clr(rtwdev, R_AX_SYS_STATUS1, B_AX_AUTO_WLPON);
+		rtw89_write32_clr(rtwdev, R_AX_GPIO_MUXCFG, B_AX_BOOT_MODE);
+		rtw89_write32_clr(rtwdev, R_AX_RSV_CTRL, B_AX_R_DIS_PRST);
+	}
+
 	if (on) {
 		cfg_seq = chip->pwr_on_seq;
 		cfg_func = chip->ops->pwr_on_func;
diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index f05c81ae5869..9d9e1b02bfc7 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -182,6 +182,7 @@
 
 #define R_AX_SYS_STATUS1 0x00F4
 #define B_AX_SEL_0XC0_MASK GENMASK(17, 16)
+#define B_AX_AUTO_WLPON BIT(10)
 #define B_AX_PAD_HCI_SEL_V2_MASK GENMASK(5, 3)
 #define MAC_AX_HCI_SEL_SDIO_UART 0
 #define MAC_AX_HCI_SEL_MULTI_USB 1
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH rtw-next v1 10/13] wifi: rtw89: Add some definitions for USB
  2025-05-04 20:47 [PATCH rtw-next v1 00/13] wifi: rtw89: Add support for USB devices Bitterblue Smith
                   ` (8 preceding siblings ...)
  2025-05-04 20:52 ` [PATCH rtw-next v1 09/13] wifi: rtw89: Fix rtw89_mac_power_switch() for USB Bitterblue Smith
@ 2025-05-04 20:53 ` Bitterblue Smith
  2025-05-13  3:52   ` Ping-Ke Shih
  2025-05-04 20:54 ` [PATCH rtw-next v1 11/13] wifi: rtw89: Add usb.{c,h} Bitterblue Smith
                   ` (4 subsequent siblings)
  14 siblings, 1 reply; 47+ messages in thread
From: Bitterblue Smith @ 2025-05-04 20:53 UTC (permalink / raw)
  To: linux-wireless@vger.kernel.org; +Cc: Ping-Ke Shih

Add various register and bit definitions which will be used by the new
USB driver.

Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
---
 drivers/net/wireless/realtek/rtw89/reg.h  | 29 +++++++++++++++++++++++
 drivers/net/wireless/realtek/rtw89/txrx.h |  1 +
 2 files changed, 30 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index 9d9e1b02bfc7..a3b83b1a92eb 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -381,6 +381,18 @@
 #define B_AX_ACH1_BUSY BIT(9)
 #define B_AX_ACH0_BUSY BIT(8)
 
+#define R_AX_USB_ENDPOINT_0 0x1060
+#define B_AX_EP_IDX GENMASK(3, 0)
+#define R_AX_USB_ENDPOINT_2 0x1068
+#define NUMP 0x1
+#define R_AX_USB_HOST_REQUEST_2 0x1078
+#define B_AX_R_USBIO_MODE BIT(4)
+#define R_AX_USB3_MAC_NPI_CONFIG_INTF_0 0x1114
+#define B_AX_SSPHY_LFPS_FILTER BIT(31)
+#define R_AX_USB_WLAN0_1 0x1174
+#define B_AX_USBRX_RST BIT(9)
+#define B_AX_USBTX_RST BIT(8)
+
 #define R_AX_PCIE_DBG_CTRL 0x11C0
 #define B_AX_DBG_DUMMY_MASK GENMASK(23, 16)
 #define B_AX_PCIE_DBG_SEL_MASK GENMASK(15, 13)
@@ -460,6 +472,17 @@
 #define R_AX_WP_PAGE_CTRL2_V1 0x17A4
 #define R_AX_WP_PAGE_INFO1_V1 0x17A8
 
+#define R_AX_USB_ENDPOINT_0_V1 0x5060
+#define B_AX_EP_IDX_V1 GENMASK(3, 0)
+#define R_AX_USB_ENDPOINT_2_V1 0x5068
+#define R_AX_USB_HOST_REQUEST_2_V1 0x5078
+#define B_AX_R_USBIO_MODE_V1 BIT(4)
+#define R_AX_USB3_MAC_NPI_CONFIG_INTF_0_V1 0x5114
+#define B_AX_SSPHY_LFPS_FILTER_V1 BIT(31)
+#define R_AX_USB_WLAN0_1_V1 0x5174
+#define B_AX_USBRX_RST_V1 BIT(9)
+#define B_AX_USBTX_RST_V1 BIT(8)
+
 #define R_AX_H2CREG_DATA0_V1 0x7140
 #define R_AX_H2CREG_DATA1_V1 0x7144
 #define R_AX_H2CREG_DATA2_V1 0x7148
@@ -1026,6 +1049,12 @@
 #define B_AX_DISPATCHER_INTN_SEL_MASK GENMASK(7, 4)
 #define B_AX_DISPATCHER_CH_SEL_MASK GENMASK(3, 0)
 
+#define R_AX_RXDMA_SETTING 0x8908
+#define B_AX_BULK_SIZE GENMASK(1, 0)
+#define USB11_BULKSIZE 0x2
+#define USB2_BULKSIZE 0x1
+#define USB3_BULKSIZE 0x0
+
 #define R_AX_RX_FUNCTION_STOP 0x8920
 #define B_AX_HDR_RX_STOP BIT(0)
 
diff --git a/drivers/net/wireless/realtek/rtw89/txrx.h b/drivers/net/wireless/realtek/rtw89/txrx.h
index 70fe7cebc9d5..3c3819973daf 100644
--- a/drivers/net/wireless/realtek/rtw89/txrx.h
+++ b/drivers/net/wireless/realtek/rtw89/txrx.h
@@ -73,6 +73,7 @@ static inline u8 rtw89_get_data_nss(struct rtw89_dev *rtwdev, u16 hw_rate)
 #define RTW89_TXWD_BODY0_FW_DL BIT(20)
 #define RTW89_TXWD_BODY0_CHANNEL_DMA GENMASK(19, 16)
 #define RTW89_TXWD_BODY0_HDR_LLC_LEN GENMASK(15, 11)
+#define RTW89_TXWD_BODY0_STF_MODE BIT(10)
 #define RTW89_TXWD_BODY0_WD_PAGE BIT(7)
 #define RTW89_TXWD_BODY0_HW_AMSDU BIT(5)
 #define RTW89_TXWD_BODY0_HW_SSN_SEL GENMASK(3, 2)
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH rtw-next v1 11/13] wifi: rtw89: Add usb.{c,h}
  2025-05-04 20:47 [PATCH rtw-next v1 00/13] wifi: rtw89: Add support for USB devices Bitterblue Smith
                   ` (9 preceding siblings ...)
  2025-05-04 20:53 ` [PATCH rtw-next v1 10/13] wifi: rtw89: Add some definitions " Bitterblue Smith
@ 2025-05-04 20:54 ` Bitterblue Smith
  2025-05-13  6:12   ` Ping-Ke Shih
  2025-05-04 20:54 ` [PATCH rtw-next v1 12/13] wifi: rtw89: Add rtw8851bu.c Bitterblue Smith
                   ` (3 subsequent siblings)
  14 siblings, 1 reply; 47+ messages in thread
From: Bitterblue Smith @ 2025-05-04 20:54 UTC (permalink / raw)
  To: linux-wireless@vger.kernel.org; +Cc: Ping-Ke Shih

Add very basic USB support. No TX/RX aggregation, no TX queues, no
switching to USB 3 mode.

RTL8851BU and RTL8832BU work.

Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
---
 drivers/net/wireless/realtek/rtw89/usb.c | 1030 ++++++++++++++++++++++
 drivers/net/wireless/realtek/rtw89/usb.h |   61 ++
 2 files changed, 1091 insertions(+)
 create mode 100644 drivers/net/wireless/realtek/rtw89/usb.c
 create mode 100644 drivers/net/wireless/realtek/rtw89/usb.h

diff --git a/drivers/net/wireless/realtek/rtw89/usb.c b/drivers/net/wireless/realtek/rtw89/usb.c
new file mode 100644
index 000000000000..6e8a544b352c
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw89/usb.c
@@ -0,0 +1,1030 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) 2025  Realtek Corporation
+ */
+
+#include <linux/usb.h>
+#include "debug.h"
+#include "mac.h"
+#include "reg.h"
+#include "txrx.h"
+#include "usb.h"
+
+static void rtw89_usb_vendorreq(struct rtw89_dev *rtwdev, u32 addr,
+				void *data, u16 len, u8 reqtype)
+{
+	struct rtw89_usb *rtwusb = rtw89_get_usb_priv(rtwdev);
+	struct usb_device *udev = rtwusb->udev;
+	unsigned int pipe;
+	u16 value, index;
+	int attempt, ret;
+
+	value = addr & 0x0000ffff;
+	index = (addr & 0x00ff0000) >> 16;
+
+	mutex_lock(&rtwusb->vendor_req_mutex);
+
+	for (attempt = 0; attempt < 10; attempt++) {
+		*rtwusb->vendor_req_buf = 0;
+
+		if (reqtype == RTW89_USB_VENQT_READ) {
+			pipe = usb_rcvctrlpipe(udev, 0);
+		} else { /* RTW89_USB_VENQT_WRITE */
+			pipe = usb_sndctrlpipe(udev, 0);
+
+			memcpy(rtwusb->vendor_req_buf, data, len);
+		}
+
+		ret = usb_control_msg(udev, pipe, RTW89_USB_VENQT, reqtype,
+				      value, index, rtwusb->vendor_req_buf,
+				      len, 500);
+
+		if (ret == len) { /* Success */
+			atomic_set(&rtwusb->continual_io_error, 0);
+
+			if (reqtype == RTW89_USB_VENQT_READ)
+				memcpy(data, rtwusb->vendor_req_buf, len);
+
+			break;
+		}
+
+		if (ret == -ESHUTDOWN || ret == -ENODEV)
+			set_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags);
+		else if (ret < 0)
+			rtw89_warn(rtwdev,
+				   "usb %s%u 0x%x fail ret=%d value=0x%x attempt=%d\n",
+				   reqtype == RTW89_USB_VENQT_READ ? "read" : "write",
+				   len * 8, addr, ret,
+				   le32_to_cpup(rtwusb->vendor_req_buf),
+				   attempt);
+		else if (ret > 0 && reqtype == RTW89_USB_VENQT_READ)
+			memcpy(data, rtwusb->vendor_req_buf, len);
+
+		if (atomic_inc_return(&rtwusb->continual_io_error) > 4) {
+			set_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags);
+			break;
+		}
+	}
+
+	mutex_unlock(&rtwusb->vendor_req_mutex);
+}
+
+static u32 rtw89_usb_read_cmac(struct rtw89_dev *rtwdev, u32 addr)
+{
+	u32 addr32, val32, shift;
+	__le32 data = 0;
+	int count;
+
+	addr32 = addr & ~0x3;
+	shift = (addr & 0x3) * 8;
+
+	for (count = 0; ; count++) {
+		rtw89_usb_vendorreq(rtwdev, addr32, &data, 4,
+				    RTW89_USB_VENQT_READ);
+
+		val32 = le32_to_cpu(data);
+
+		if (val32 != RTW89_R32_DEAD)
+			break;
+
+		if (count >= MAC_REG_POOL_COUNT) {
+			rtw89_warn(rtwdev, "%s: addr %#x = %#x\n",
+				   __func__, addr32, val32);
+			val32 = RTW89_R32_DEAD;
+			break;
+		}
+
+		rtw89_write32(rtwdev, R_AX_CK_EN, B_AX_CMAC_ALLCKEN);
+	}
+
+	return val32 >> shift;
+}
+
+static u8 rtw89_usb_ops_read8(struct rtw89_dev *rtwdev, u32 addr)
+{
+	u8 data = 0;
+
+	if (ACCESS_CMAC(addr))
+		return rtw89_usb_read_cmac(rtwdev, addr);
+
+	rtw89_usb_vendorreq(rtwdev, addr, &data, 1, RTW89_USB_VENQT_READ);
+
+	return data;
+}
+
+static u16 rtw89_usb_ops_read16(struct rtw89_dev *rtwdev, u32 addr)
+{
+	__le16 data = 0;
+
+	if (ACCESS_CMAC(addr))
+		return rtw89_usb_read_cmac(rtwdev, addr);
+
+	rtw89_usb_vendorreq(rtwdev, addr, &data, 2, RTW89_USB_VENQT_READ);
+
+	return le16_to_cpu(data);
+}
+
+static u32 rtw89_usb_ops_read32(struct rtw89_dev *rtwdev, u32 addr)
+{
+	__le32 data = 0;
+
+	if (ACCESS_CMAC(addr))
+		return rtw89_usb_read_cmac(rtwdev, addr);
+
+	rtw89_usb_vendorreq(rtwdev, addr, &data, 4,
+			    RTW89_USB_VENQT_READ);
+
+	return le32_to_cpu(data);
+}
+
+static void rtw89_usb_ops_write8(struct rtw89_dev *rtwdev, u32 addr, u8 val)
+{
+	u8 data = val;
+
+	rtw89_usb_vendorreq(rtwdev, addr, &data, 1, RTW89_USB_VENQT_WRITE);
+}
+
+static void rtw89_usb_ops_write16(struct rtw89_dev *rtwdev, u32 addr, u16 val)
+{
+	__le16 data = cpu_to_le16(val);
+
+	rtw89_usb_vendorreq(rtwdev, addr, &data, 2, RTW89_USB_VENQT_WRITE);
+}
+
+static void rtw89_usb_ops_write32(struct rtw89_dev *rtwdev, u32 addr, u32 val)
+{
+	__le32 data = cpu_to_le32(val);
+
+	rtw89_usb_vendorreq(rtwdev, addr, &data, 4, RTW89_USB_VENQT_WRITE);
+}
+
+static u32
+rtw89_usb_ops_check_and_reclaim_tx_resource(struct rtw89_dev *rtwdev,
+					    u8 txch)
+{
+	if (txch == RTW89_TXCH_CH12)
+		return 1;
+
+	return 42; /* TODO some kind of calculation? */
+}
+
+static void rtw89_usb_ops_tx_kick_off(struct rtw89_dev *rtwdev, u8 txch)
+{
+	/* TODO later. for now transmit every frame right away in
+	 * rtw89_usb_ops_tx_write
+	 */
+}
+
+static u8 rtw89_usb_get_bulkout_id(u8 ch_dma)
+{
+	switch (ch_dma) {
+	case RTW89_DMA_ACH0:
+		return 3;
+	case RTW89_DMA_ACH1:
+		return 4;
+	case RTW89_DMA_ACH2:
+		return 5;
+	case RTW89_DMA_ACH3:
+		return 6;
+	default:
+	case RTW89_DMA_B0MG:
+		return 0;
+	case RTW89_DMA_B0HI:
+		return 1;
+	case RTW89_DMA_H2C:
+		return 2;
+	}
+}
+
+static int rtw89_usb_write_port(struct rtw89_dev *rtwdev, u8 ch_dma,
+				void *data, int len, usb_complete_t cb,
+				void *context)
+{
+	struct rtw89_usb *rtwusb = rtw89_get_usb_priv(rtwdev);
+	struct usb_device *usbd = rtwusb->udev;
+	struct urb *urb;
+	u8 bulkout_id = rtw89_usb_get_bulkout_id(ch_dma);
+	unsigned int pipe;
+	int ret;
+
+	if (test_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags))
+		return 0;
+
+	urb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!urb)
+		return -ENOMEM;
+
+	pipe = usb_sndbulkpipe(usbd, rtwusb->out_pipe[bulkout_id]);
+
+	usb_fill_bulk_urb(urb, usbd, pipe, data, len, cb, context);
+	urb->transfer_flags |= URB_ZERO_PACKET;
+	ret = usb_submit_urb(urb, GFP_ATOMIC);
+
+	if (ret)
+		usb_free_urb(urb);
+
+	if (ret == -ENODEV)
+		set_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags);
+
+	return ret;
+}
+
+static void rtw89_usb_write_port_complete_fwcmd(struct urb *urb)
+{
+	struct rtw89_usb_tx_ctrl_block *txcb = urb->context;
+	struct rtw89_dev *rtwdev = txcb->rtwdev;
+
+	switch (urb->status) {
+	case 0:
+	case -EPIPE:
+	case -EPROTO:
+	case -EINPROGRESS:
+	case -ENOENT:
+	case -ECONNRESET:
+		break;
+	default:
+		set_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags);
+		break;
+	}
+
+	skb_queue_purge(&txcb->tx_ack_queue);
+	kfree(txcb);
+	usb_free_urb(urb);
+}
+
+static int rtw89_usb_fwcmd_submit(struct rtw89_dev *rtwdev,
+				  struct rtw89_core_tx_request *tx_req)
+{
+	struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info;
+	struct rtw89_usb_tx_ctrl_block *txcb;
+	struct sk_buff *skb = tx_req->skb;
+	int txdesc_size = rtwdev->chip->h2c_desc_size;
+	void *txdesc;
+	int ret;
+
+	if (((desc_info->pkt_size + txdesc_size) % 512) == 0) {
+		rtw89_info(rtwdev, "avoiding multiple of 512\n");
+		desc_info->pkt_size += 4;
+		skb_put(skb, 4);
+	}
+
+	txcb = kmalloc(sizeof(*txcb), GFP_ATOMIC);
+	if (!txcb)
+		return -ENOMEM;
+
+	txdesc = skb_push(skb, txdesc_size);
+	memset(txdesc, 0, txdesc_size);
+	rtw89_chip_fill_txdesc_fwcmd(rtwdev, desc_info, txdesc);
+
+	txcb->rtwdev = rtwdev;
+	skb_queue_head_init(&txcb->tx_ack_queue);
+
+	skb_queue_tail(&txcb->tx_ack_queue, skb);
+
+	ret = rtw89_usb_write_port(rtwdev, RTW89_DMA_H2C, skb->data, skb->len,
+				   rtw89_usb_write_port_complete_fwcmd, txcb);
+
+	if (ret) {
+		rtw89_err(rtwdev, "%s failed: %d\n", __func__, ret);
+
+		skb_dequeue(&txcb->tx_ack_queue);
+		kfree(txcb);
+	}
+
+	return ret;
+}
+
+static void rtw89_usb_write_port_complete(struct urb *urb)
+{
+	struct rtw89_usb_tx_ctrl_block *txcb = urb->context;
+	struct rtw89_dev *rtwdev = txcb->rtwdev;
+	struct ieee80211_tx_info *info;
+	struct sk_buff *skb;
+
+	while (true) {
+		skb = skb_dequeue(&txcb->tx_ack_queue);
+		if (!skb)
+			break;
+
+		info = IEEE80211_SKB_CB(skb);
+		ieee80211_tx_info_clear_status(info);
+
+		if (urb->status == 0) {
+			if (info->flags & IEEE80211_TX_CTL_NO_ACK)
+				info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED;
+			else
+				info->flags |= IEEE80211_TX_STAT_ACK;
+		}
+
+		ieee80211_tx_status_irqsafe(rtwdev->hw, skb);
+	}
+
+	switch (urb->status) {
+	case 0:
+	case -EPIPE:
+	case -EPROTO:
+	case -EINPROGRESS:
+	case -ENOENT:
+	case -ECONNRESET:
+		break;
+	default:
+		set_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags);
+		break;
+	}
+
+	kfree(txcb);
+	usb_free_urb(urb);
+}
+
+static int rtw89_usb_ops_tx_write(struct rtw89_dev *rtwdev,
+				  struct rtw89_core_tx_request *tx_req)
+{
+	struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info;
+	const struct rtw89_chip_info *chip = rtwdev->chip;
+	struct rtw89_usb_tx_ctrl_block *txcb;
+	struct sk_buff *skb = tx_req->skb;
+	struct rtw89_txwd_body *txdesc;
+	u32 txdesc_size;
+	int ret, len;
+
+	if ((desc_info->ch_dma == RTW89_TXCH_CH12 ||
+	     tx_req->tx_type == RTW89_CORE_TX_TYPE_FWCMD) &&
+	    (desc_info->ch_dma != RTW89_TXCH_CH12 ||
+	     tx_req->tx_type != RTW89_CORE_TX_TYPE_FWCMD)) {
+		rtw89_err(rtwdev, "dma channel %d/TX type %d mismatch\n",
+			  desc_info->ch_dma, tx_req->tx_type);
+		return -EINVAL;
+	}
+
+	if (desc_info->ch_dma == RTW89_TXCH_CH12)
+		return rtw89_usb_fwcmd_submit(rtwdev, tx_req);
+
+	txcb = kmalloc(sizeof(*txcb), GFP_ATOMIC);
+	if (!txcb)
+		return -ENOMEM;
+
+	txdesc_size = chip->txwd_body_size;
+	if (desc_info->en_wd_info)
+		txdesc_size += chip->txwd_info_size;
+
+	txdesc = (struct rtw89_txwd_body *)(skb->data - txdesc_size);
+	len = skb->len + txdesc_size;
+	memset(txdesc, 0, txdesc_size);
+	rtw89_chip_fill_txdesc(rtwdev, desc_info, txdesc);
+
+	le32p_replace_bits(&txdesc->dword0, 1, RTW89_TXWD_BODY0_STF_MODE);
+
+	txcb->rtwdev = rtwdev;
+	skb_queue_head_init(&txcb->tx_ack_queue);
+
+	skb_queue_tail(&txcb->tx_ack_queue, skb);
+
+	ret = rtw89_usb_write_port(rtwdev, desc_info->ch_dma, txdesc, len,
+				   rtw89_usb_write_port_complete, txcb);
+	if (ret) {
+		rtw89_err(rtwdev, "%s failed: %d\n", __func__, ret);
+
+		skb_dequeue(&txcb->tx_ack_queue);
+		kfree(txcb);
+	}
+
+	return ret;
+}
+
+static void rtw89_usb_rx_handler(struct work_struct *work)
+{
+	struct rtw89_usb *rtwusb = container_of(work, struct rtw89_usb, rx_work);
+	struct rtw89_dev *rtwdev = rtwusb->rtwdev;
+	struct rtw89_rx_desc_info desc_info;
+	struct sk_buff *rx_skb;
+	struct sk_buff *skb;
+	u32 pkt_offset;
+	int limit;
+
+	for (limit = 0; limit < 200; limit++) {
+		rx_skb = skb_dequeue(&rtwusb->rx_queue);
+		if (!rx_skb)
+			break;
+
+		if (skb_queue_len(&rtwusb->rx_queue) >= RTW89_USB_MAX_RXQ_LEN) {
+			rtw89_warn(rtwdev, "rx_queue overflow\n");
+			dev_kfree_skb_any(rx_skb);
+			continue;
+		}
+
+		memset(&desc_info, 0, sizeof(desc_info));
+		rtw89_chip_query_rxdesc(rtwdev, &desc_info, rx_skb->data, 0);
+
+		skb = rtw89_alloc_skb_for_rx(rtwdev, desc_info.pkt_size);
+		if (!skb) {
+			rtw89_debug(rtwdev, RTW89_DBG_HCI,
+				    "failed to allocate RX skb of size %u\n",
+				    desc_info.pkt_size);
+			continue;
+		}
+
+		pkt_offset = desc_info.offset + desc_info.rxd_len;
+
+		skb_put_data(skb, rx_skb->data + pkt_offset,
+			     desc_info.pkt_size);
+
+		rtw89_core_rx(rtwdev, &desc_info, skb);
+
+		if (skb_queue_len(&rtwusb->rx_free_queue) >= RTW89_USB_RX_SKB_NUM)
+			dev_kfree_skb_any(rx_skb);
+		else
+			skb_queue_tail(&rtwusb->rx_free_queue, rx_skb);
+	}
+
+	if (limit == 200)
+		rtw89_debug(rtwdev, RTW89_DBG_HCI,
+			    "left %d rx skbs in the queue for later\n",
+			    skb_queue_len(&rtwusb->rx_queue));
+}
+
+static void rtw89_usb_read_port_complete(struct urb *urb);
+
+static void rtw89_usb_rx_resubmit(struct rtw89_usb *rtwusb,
+				  struct rtw89_usb_rx_ctrl_block *rxcb,
+				  gfp_t gfp)
+{
+	struct rtw89_dev *rtwdev = rtwusb->rtwdev;
+	struct sk_buff *rx_skb;
+	int error;
+
+	rx_skb = skb_dequeue(&rtwusb->rx_free_queue);
+	if (!rx_skb)
+		rx_skb = alloc_skb(RTW89_USB_RECVBUF_SZ, gfp);
+
+	if (!rx_skb)
+		goto try_later;
+
+	skb_reset_tail_pointer(rx_skb);
+	rx_skb->len = 0;
+
+	rxcb->rx_skb = rx_skb;
+
+	usb_fill_bulk_urb(rxcb->rx_urb, rtwusb->udev,
+			  usb_rcvbulkpipe(rtwusb->udev, rtwusb->in_pipe),
+			  rxcb->rx_skb->data, RTW89_USB_RECVBUF_SZ,
+			  rtw89_usb_read_port_complete, rxcb);
+
+	error = usb_submit_urb(rxcb->rx_urb, gfp);
+	if (error) {
+		skb_queue_tail(&rtwusb->rx_free_queue, rxcb->rx_skb);
+
+		if (error == -ENODEV)
+			set_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags);
+		else
+			rtw89_err(rtwdev, "Err sending rx data urb %d\n",
+				  error);
+
+		if (error == -ENOMEM)
+			goto try_later;
+	}
+
+	return;
+
+try_later:
+	rxcb->rx_skb = NULL;
+	queue_work(rtwusb->rxwq, &rtwusb->rx_urb_work);
+}
+
+static void rtw89_usb_rx_resubmit_work(struct work_struct *work)
+{
+	struct rtw89_usb *rtwusb = container_of(work, struct rtw89_usb, rx_urb_work);
+	struct rtw89_usb_rx_ctrl_block *rxcb;
+	int i;
+
+	for (i = 0; i < RTW89_USB_RXCB_NUM; i++) {
+		rxcb = &rtwusb->rx_cb[i];
+
+		if (!rxcb->rx_skb)
+			rtw89_usb_rx_resubmit(rtwusb, rxcb, GFP_ATOMIC);
+	}
+}
+
+static void rtw89_usb_read_port_complete(struct urb *urb)
+{
+	struct rtw89_usb_rx_ctrl_block *rxcb = urb->context;
+	struct rtw89_dev *rtwdev = rxcb->rtwdev;
+	struct rtw89_usb *rtwusb = rtw89_get_usb_priv(rtwdev);
+	struct sk_buff *skb = rxcb->rx_skb;
+
+	if (urb->status == 0) {
+		if (urb->actual_length > urb->transfer_buffer_length ||
+		    urb->actual_length < sizeof(struct rtw89_rxdesc_short)) {
+			rtw89_err(rtwdev, "failed to get urb length: %d\n",
+				  urb->actual_length);
+			skb_queue_tail(&rtwusb->rx_free_queue, skb);
+		} else {
+			skb_put(skb, urb->actual_length);
+			skb_queue_tail(&rtwusb->rx_queue, skb);
+			queue_work(rtwusb->rxwq, &rtwusb->rx_work);
+		}
+
+		rtw89_usb_rx_resubmit(rtwusb, rxcb, GFP_ATOMIC);
+	} else {
+		skb_queue_tail(&rtwusb->rx_free_queue, skb);
+
+		if (atomic_inc_return(&rtwusb->continual_io_error) > 4)
+			set_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags);
+
+		switch (urb->status) {
+		case -EINVAL:
+		case -EPIPE:
+		case -ENODEV:
+		case -ESHUTDOWN:
+			set_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags);
+			break;
+		case -EPROTO:
+		case -EILSEQ:
+		case -ETIME:
+		case -ECOMM:
+		case -EOVERFLOW:
+		case -ENOENT:
+			break;
+		case -EINPROGRESS:
+			rtw89_info(rtwdev, "URB is in progress\n");
+			break;
+		default:
+			rtw89_err(rtwdev, "%s status %d\n",
+				  __func__, urb->status);
+			break;
+		}
+	}
+}
+
+static void rtw89_usb_cancel_rx_bufs(struct rtw89_usb *rtwusb)
+{
+	struct rtw89_usb_rx_ctrl_block *rxcb;
+	int i;
+
+	for (i = 0; i < RTW89_USB_RXCB_NUM; i++) {
+		rxcb = &rtwusb->rx_cb[i];
+		usb_kill_urb(rxcb->rx_urb);
+	}
+}
+
+static void rtw89_usb_free_rx_bufs(struct rtw89_usb *rtwusb)
+{
+	struct rtw89_usb_rx_ctrl_block *rxcb;
+	int i;
+
+	for (i = 0; i < RTW89_USB_RXCB_NUM; i++) {
+		rxcb = &rtwusb->rx_cb[i];
+
+		usb_kill_urb(rxcb->rx_urb);
+		usb_free_urb(rxcb->rx_urb);
+	}
+}
+
+static int rtw89_usb_alloc_rx_bufs(struct rtw89_usb *rtwusb)
+{
+	struct rtw89_usb_rx_ctrl_block *rxcb;
+	int i;
+
+	for (i = 0; i < RTW89_USB_RXCB_NUM; i++) {
+		rxcb = &rtwusb->rx_cb[i];
+
+		rxcb->rtwdev = rtwusb->rtwdev;
+		rxcb->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!rxcb->rx_urb) {
+			rtw89_usb_free_rx_bufs(rtwusb);
+			return -ENOMEM;
+		}
+	}
+
+	return 0;
+}
+
+static int rtw89_usb_init_rx(struct rtw89_dev *rtwdev)
+{
+	struct rtw89_usb *rtwusb = rtw89_get_usb_priv(rtwdev);
+	struct sk_buff *rx_skb;
+	int i;
+
+	rtwusb->rxwq = alloc_workqueue("rtw89_usb: rx wq", WQ_BH, 0);
+	if (!rtwusb->rxwq) {
+		rtw89_err(rtwdev, "failed to create RX work queue\n");
+		return -ENOMEM;
+	}
+
+	skb_queue_head_init(&rtwusb->rx_queue);
+	skb_queue_head_init(&rtwusb->rx_free_queue);
+
+	INIT_WORK(&rtwusb->rx_work, rtw89_usb_rx_handler);
+	INIT_WORK(&rtwusb->rx_urb_work, rtw89_usb_rx_resubmit_work);
+
+	for (i = 0; i < RTW89_USB_RX_SKB_NUM; i++) {
+		rx_skb = alloc_skb(RTW89_USB_RECVBUF_SZ, GFP_KERNEL);
+		if (rx_skb)
+			skb_queue_tail(&rtwusb->rx_free_queue, rx_skb);
+	}
+
+	return 0;
+}
+
+static void rtw89_usb_deinit_rx(struct rtw89_dev *rtwdev)
+{
+	struct rtw89_usb *rtwusb = rtw89_get_usb_priv(rtwdev);
+
+	skb_queue_purge(&rtwusb->rx_queue);
+
+	destroy_workqueue(rtwusb->rxwq);
+
+	skb_queue_purge(&rtwusb->rx_free_queue);
+}
+
+static void rtw89_usb_start_rx(struct rtw89_dev *rtwdev)
+{
+	struct rtw89_usb *rtwusb = rtw89_get_usb_priv(rtwdev);
+	int i;
+
+	for (i = 0; i < RTW89_USB_RXCB_NUM; i++)
+		rtw89_usb_rx_resubmit(rtwusb, &rtwusb->rx_cb[i], GFP_KERNEL);
+}
+
+static void rtw89_usb_ops_reset(struct rtw89_dev *rtwdev)
+{
+	/* TODO: anything to do here? */
+}
+
+static int rtw89_usb_ops_start(struct rtw89_dev *rtwdev)
+{
+	return 0; /* Nothing to do. */
+}
+
+static void rtw89_usb_ops_stop(struct rtw89_dev *rtwdev)
+{
+	/* Nothing to do. */
+}
+
+static void rtw89_usb_ops_pause(struct rtw89_dev *rtwdev, bool pause)
+{
+	/* Nothing to do? */
+}
+
+static void rtw89_usb_ops_switch_mode(struct rtw89_dev *rtwdev, bool low_power)
+{
+	/* Nothing to do. */
+}
+
+static int rtw89_usb_ops_deinit(struct rtw89_dev *rtwdev)
+{
+	return 0; /* Nothing to do. */
+}
+
+static int rtw89_usb_ops_mac_pre_init(struct rtw89_dev *rtwdev)
+{
+	u32 val32;
+
+	rtw89_write32_set(rtwdev, R_AX_USB_HOST_REQUEST_2, B_AX_R_USBIO_MODE);
+
+	/* fix USB IO hang suggest by chihhanli@realtek.com */
+	rtw89_write32_clr(rtwdev, R_AX_USB_WLAN0_1,
+			  B_AX_USBRX_RST | B_AX_USBTX_RST);
+
+	val32 = rtw89_read32(rtwdev, R_AX_HCI_FUNC_EN);
+	val32 &= ~(B_AX_HCI_RXDMA_EN | B_AX_HCI_TXDMA_EN);
+	rtw89_write32(rtwdev, R_AX_HCI_FUNC_EN, val32);
+
+	val32 |= B_AX_HCI_RXDMA_EN | B_AX_HCI_TXDMA_EN;
+	rtw89_write32(rtwdev, R_AX_HCI_FUNC_EN, val32);
+	/* fix USB TRX hang suggest by chihhanli@realtek.com */
+
+	return 0;
+}
+
+static int rtw89_usb_ops_mac_pre_deinit(struct rtw89_dev *rtwdev)
+{
+	return 0; /* Nothing to do. */
+}
+
+static int rtw89_usb_ops_mac_post_init(struct rtw89_dev *rtwdev)
+{
+	struct rtw89_usb *rtwusb = rtw89_get_usb_priv(rtwdev);
+	enum usb_device_speed speed;
+	u32 ep;
+
+	rtw89_write32_clr(rtwdev, R_AX_USB3_MAC_NPI_CONFIG_INTF_0,
+			  B_AX_SSPHY_LFPS_FILTER);
+
+	speed = rtwusb->udev->speed;
+
+	if (speed == USB_SPEED_SUPER)
+		rtw89_write8(rtwdev, R_AX_RXDMA_SETTING, USB3_BULKSIZE);
+	else if (speed == USB_SPEED_HIGH)
+		rtw89_write8(rtwdev, R_AX_RXDMA_SETTING, USB2_BULKSIZE);
+	else
+		rtw89_write8(rtwdev, R_AX_RXDMA_SETTING, USB11_BULKSIZE);
+
+	for (ep = 5; ep <= 12; ep++) {
+		if (ep == 8)
+			continue;
+
+		rtw89_write8_mask(rtwdev, R_AX_USB_ENDPOINT_0,
+				  B_AX_EP_IDX, ep);
+		rtw89_write8(rtwdev, R_AX_USB_ENDPOINT_2 + 1, NUMP);
+	}
+
+	return 0;
+}
+
+static void rtw89_usb_ops_recalc_int_mit(struct rtw89_dev *rtwdev)
+{
+	/* Nothing to do. */
+}
+
+static int rtw89_usb_ops_mac_lv1_rcvy(struct rtw89_dev *rtwdev,
+				      enum rtw89_lv1_rcvy_step step)
+{
+	u32 reg, mask;
+
+	switch (rtwdev->chip->chip_id) {
+	case RTL8851B:
+	case RTL8852A:
+	case RTL8852B:
+		reg = R_AX_USB_WLAN0_1;
+		mask = B_AX_USBRX_RST | B_AX_USBTX_RST;
+		break;
+	case RTL8852C:
+		reg = R_AX_USB_WLAN0_1_V1;
+		mask = B_AX_USBRX_RST_V1 | B_AX_USBTX_RST_V1;
+		break;
+	default:
+		rtw89_err(rtwdev, "%s: fix me\n", __func__);
+		return -EOPNOTSUPP;
+	}
+
+	switch (step) {
+	case RTW89_LV1_RCVY_STEP_1:
+		rtw89_write32_set(rtwdev, reg, mask);
+
+		msleep(30);
+
+		break;
+	case RTW89_LV1_RCVY_STEP_2:
+		rtw89_write32_clr(rtwdev, reg, mask);
+
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void rtw89_usb_ops_dump_err_status(struct rtw89_dev *rtwdev)
+{
+	rtw89_warn(rtwdev, "%s TODO\n", __func__);
+}
+
+static const
+struct rtw89_dle_mem *rtw89_usb_ops_dle_mem(struct rtw89_dev *rtwdev,
+					    u8 qta_mode)
+{
+	struct rtw89_usb *rtwusb = rtw89_get_usb_priv(rtwdev);
+
+	if (rtwusb->udev->speed == USB_SPEED_SUPER)
+		return &rtwdev->chip->dle_mem_usb3[qta_mode];
+	else
+		return &rtwdev->chip->dle_mem_usb2[qta_mode];
+}
+
+static const struct rtw89_hci_ops rtw89_usb_ops = {
+	.tx_write	= rtw89_usb_ops_tx_write,
+	.tx_kick_off	= rtw89_usb_ops_tx_kick_off,
+	.flush_queues	= NULL, /* Not needed? */
+	.reset		= rtw89_usb_ops_reset,
+	.start		= rtw89_usb_ops_start,
+	.stop		= rtw89_usb_ops_stop,
+	.pause		= rtw89_usb_ops_pause,
+	.switch_mode	= rtw89_usb_ops_switch_mode,
+	.recalc_int_mit = rtw89_usb_ops_recalc_int_mit,
+
+	.read8		= rtw89_usb_ops_read8,
+	.read16		= rtw89_usb_ops_read16,
+	.read32		= rtw89_usb_ops_read32,
+	.write8		= rtw89_usb_ops_write8,
+	.write16	= rtw89_usb_ops_write16,
+	.write32	= rtw89_usb_ops_write32,
+
+	.mac_pre_init	= rtw89_usb_ops_mac_pre_init,
+	.mac_pre_deinit	= rtw89_usb_ops_mac_pre_deinit,
+	.mac_post_init	= rtw89_usb_ops_mac_post_init,
+	.deinit		= rtw89_usb_ops_deinit,
+
+	.check_and_reclaim_tx_resource = rtw89_usb_ops_check_and_reclaim_tx_resource,
+	.mac_lv1_rcvy	= rtw89_usb_ops_mac_lv1_rcvy,
+	.dump_err_status = rtw89_usb_ops_dump_err_status,
+	.napi_poll	= NULL,
+
+	.recovery_start = NULL,
+	.recovery_complete = NULL,
+
+	.ctrl_txdma_ch	= NULL,
+	.ctrl_txdma_fw_ch = NULL,
+	.ctrl_trxhci	= NULL,
+	.poll_txdma_ch_idle = NULL,
+
+	.clr_idx_all	= NULL,
+	.clear		= NULL,
+	.disable_intr	= NULL,
+	.enable_intr	= NULL,
+	.rst_bdram	= NULL,
+
+	.dle_mem	= rtw89_usb_ops_dle_mem,
+};
+
+static int rtw89_usb_parse(struct rtw89_dev *rtwdev,
+			   struct usb_interface *intf)
+{
+	struct usb_host_interface *host_interface = &intf->altsetting[0];
+	struct usb_interface_descriptor *intf_desc = &host_interface->desc;
+	struct rtw89_usb *rtwusb = rtw89_get_usb_priv(rtwdev);
+	struct usb_endpoint_descriptor *endpoint;
+	int num_out_pipes = 0;
+	u8 num;
+	int i;
+
+	if (intf_desc->bNumEndpoints > RTW89_MAX_ENDPOINT_NUM) {
+		rtw89_err(rtwdev, "found %d endpoints, expected %d max\n",
+			  intf_desc->bNumEndpoints, RTW89_MAX_ENDPOINT_NUM);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < intf_desc->bNumEndpoints; i++) {
+		endpoint = &host_interface->endpoint[i].desc;
+		num = usb_endpoint_num(endpoint);
+
+		if (usb_endpoint_dir_in(endpoint) &&
+		    usb_endpoint_xfer_bulk(endpoint)) {
+			if (rtwusb->in_pipe) {
+				rtw89_err(rtwdev,
+					  "found more than 1 bulk in endpoint\n");
+				return -EINVAL;
+			}
+
+			rtwusb->in_pipe = num;
+		}
+
+		if (usb_endpoint_dir_out(endpoint) &&
+		    usb_endpoint_xfer_bulk(endpoint)) {
+			if (num_out_pipes >= RTW89_MAX_BULKOUT_NUM) {
+				rtw89_err(rtwdev,
+					  "found more than %d bulk out endpoints\n",
+					  RTW89_MAX_BULKOUT_NUM);
+				return -EINVAL;
+			}
+
+			rtwusb->out_pipe[num_out_pipes++] = num;
+		}
+	}
+
+	if (num_out_pipes < 1) {
+		rtw89_err(rtwdev, "no bulk out endpoints found\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int rtw89_usb_intf_init(struct rtw89_dev *rtwdev,
+			       struct usb_interface *intf)
+{
+	struct rtw89_usb *rtwusb = rtw89_get_usb_priv(rtwdev);
+	int ret;
+
+	ret = rtw89_usb_parse(rtwdev, intf);
+	if (ret)
+		return ret;
+
+	rtwusb->vendor_req_buf = kmalloc(sizeof(u32), GFP_KERNEL);
+	if (!rtwusb->vendor_req_buf)
+		return -ENOMEM;
+
+	rtwusb->udev = usb_get_dev(interface_to_usbdev(intf));
+
+	usb_set_intfdata(intf, rtwdev->hw);
+
+	SET_IEEE80211_DEV(rtwdev->hw, &intf->dev);
+
+	mutex_init(&rtwusb->vendor_req_mutex);
+
+	return 0;
+}
+
+static void rtw89_usb_intf_deinit(struct rtw89_dev *rtwdev,
+				  struct usb_interface *intf)
+{
+	struct rtw89_usb *rtwusb = rtw89_get_usb_priv(rtwdev);
+
+	mutex_destroy(&rtwusb->vendor_req_mutex);
+	usb_put_dev(rtwusb->udev);
+	kfree(rtwusb->vendor_req_buf);
+	usb_set_intfdata(intf, NULL);
+}
+
+int rtw89_usb_probe(struct usb_interface *intf,
+		    const struct usb_device_id *id)
+{
+	const struct rtw89_driver_info *info;
+	struct rtw89_dev *rtwdev;
+	struct rtw89_usb *rtwusb;
+	int ret;
+
+	info = (const struct rtw89_driver_info *)id->driver_info;
+
+	rtwdev = rtw89_alloc_ieee80211_hw(&intf->dev,
+					  sizeof(struct rtw89_usb),
+					  info->chip, info->variant);
+	if (!rtwdev) {
+		dev_err(&intf->dev, "failed to allocate hw\n");
+		return -ENOMEM;
+	}
+
+	rtwusb = rtw89_get_usb_priv(rtwdev);
+	rtwusb->rtwdev = rtwdev;
+
+	rtwdev->hci.ops = &rtw89_usb_ops;
+	rtwdev->hci.type = RTW89_HCI_TYPE_USB;
+
+	ret = rtw89_usb_intf_init(rtwdev, intf);
+	if (ret) {
+		rtw89_err(rtwdev, "failed to initialise intf: %d\n", ret);
+		goto err_free_hw;
+	}
+
+	ret = rtw89_usb_alloc_rx_bufs(rtwusb);
+	if (ret)
+		goto err_intf_deinit;
+
+	ret = rtw89_usb_init_rx(rtwdev);
+	if (ret)
+		goto err_free_rx_bufs;
+
+	ret = rtw89_core_init(rtwdev);
+	if (ret) {
+		rtw89_err(rtwdev, "failed to initialise core: %d\n", ret);
+		goto err_deinit_rx;
+	}
+
+	ret = rtw89_chip_info_setup(rtwdev);
+	if (ret) {
+		rtw89_err(rtwdev, "failed to setup chip information\n");
+		goto err_core_deinit;
+	}
+
+	ret = rtw89_core_register(rtwdev);
+	if (ret) {
+		rtw89_err(rtwdev, "failed to register core\n");
+		goto err_core_deinit;
+	}
+
+	rtw89_usb_start_rx(rtwdev);
+
+	set_bit(RTW89_FLAG_PROBE_DONE, rtwdev->flags);
+
+	return 0;
+
+err_core_deinit:
+	rtw89_core_deinit(rtwdev);
+err_deinit_rx:
+	rtw89_usb_deinit_rx(rtwdev);
+err_free_rx_bufs:
+	rtw89_usb_free_rx_bufs(rtwusb);
+err_intf_deinit:
+	rtw89_usb_intf_deinit(rtwdev, intf);
+err_free_hw:
+	rtw89_free_ieee80211_hw(rtwdev);
+
+	return ret;
+}
+EXPORT_SYMBOL(rtw89_usb_probe);
+
+void rtw89_usb_disconnect(struct usb_interface *intf)
+{
+	struct ieee80211_hw *hw = usb_get_intfdata(intf);
+	struct rtw89_dev *rtwdev;
+	struct rtw89_usb *rtwusb;
+
+	if (!hw)
+		return;
+
+	rtwdev = hw->priv;
+	rtwusb = rtw89_get_usb_priv(rtwdev);
+
+	rtw89_usb_cancel_rx_bufs(rtwusb);
+
+	rtw89_core_unregister(rtwdev);
+	rtw89_core_deinit(rtwdev);
+	rtw89_usb_deinit_rx(rtwdev);
+	rtw89_usb_free_rx_bufs(rtwusb);
+	rtw89_usb_intf_deinit(rtwdev, intf);
+	rtw89_free_ieee80211_hw(rtwdev);
+}
+EXPORT_SYMBOL(rtw89_usb_disconnect);
+
+MODULE_AUTHOR("Bitterblue Smith <rtl8821cerfe2@gmail.com>");
+MODULE_DESCRIPTION("Realtek USB 802.11ax wireless driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/realtek/rtw89/usb.h b/drivers/net/wireless/realtek/rtw89/usb.h
new file mode 100644
index 000000000000..86caae1b9d0b
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw89/usb.h
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2025  Realtek Corporation
+ */
+
+#ifndef __RTW89_USB_H__
+#define __RTW89_USB_H__
+
+#define RTW89_USB_VENQT			0x05
+#define RTW89_USB_VENQT_READ		0xc0
+#define RTW89_USB_VENQT_WRITE		0x40
+
+#define RTW89_USB_RECVBUF_SZ		20480
+#define RTW89_USB_RXCB_NUM		8
+#define RTW89_USB_RX_SKB_NUM		16
+#define RTW89_USB_MAX_RXQ_LEN		512
+
+#define RTW89_MAX_ENDPOINT_NUM		9
+#define RTW89_MAX_BULKOUT_NUM		7
+
+struct rtw89_usb_rx_ctrl_block {
+	struct rtw89_dev *rtwdev;
+	struct urb *rx_urb;
+	struct sk_buff *rx_skb;
+};
+
+struct rtw89_usb_tx_ctrl_block {
+	struct rtw89_dev *rtwdev;
+	struct sk_buff_head tx_ack_queue;
+};
+
+struct rtw89_usb {
+	struct rtw89_dev *rtwdev;
+	struct usb_device *udev;
+
+	/* Serialises the register accesses. */
+	struct mutex vendor_req_mutex;
+	__le32 *vendor_req_buf;
+
+	atomic_t continual_io_error;
+
+	u8 in_pipe;
+	u8 out_pipe[RTW89_MAX_BULKOUT_NUM];
+
+	struct workqueue_struct *rxwq;
+	struct rtw89_usb_rx_ctrl_block rx_cb[RTW89_USB_RXCB_NUM];
+	struct sk_buff_head rx_queue;
+	struct sk_buff_head rx_free_queue;
+	struct work_struct rx_work;
+	struct work_struct rx_urb_work;
+};
+
+static inline struct rtw89_usb *rtw89_get_usb_priv(struct rtw89_dev *rtwdev)
+{
+	return (struct rtw89_usb *)rtwdev->priv;
+}
+
+int rtw89_usb_probe(struct usb_interface *intf,
+		    const struct usb_device_id *id);
+void rtw89_usb_disconnect(struct usb_interface *intf);
+
+#endif
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH rtw-next v1 12/13] wifi: rtw89: Add rtw8851bu.c
  2025-05-04 20:47 [PATCH rtw-next v1 00/13] wifi: rtw89: Add support for USB devices Bitterblue Smith
                   ` (10 preceding siblings ...)
  2025-05-04 20:54 ` [PATCH rtw-next v1 11/13] wifi: rtw89: Add usb.{c,h} Bitterblue Smith
@ 2025-05-04 20:54 ` Bitterblue Smith
  2025-05-13  6:14   ` Ping-Ke Shih
  2025-05-04 20:55 ` [PATCH rtw-next v1 13/13] wifi: rtw89: Enable the new USB modules Bitterblue Smith
                   ` (2 subsequent siblings)
  14 siblings, 1 reply; 47+ messages in thread
From: Bitterblue Smith @ 2025-05-04 20:54 UTC (permalink / raw)
  To: linux-wireless@vger.kernel.org; +Cc: Ping-Ke Shih

This is the entry point for the new rtw89_8851bu module.

Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
---
 .../net/wireless/realtek/rtw89/rtw8851bu.c    | 33 +++++++++++++++++++
 1 file changed, 33 insertions(+)
 create mode 100644 drivers/net/wireless/realtek/rtw89/rtw8851bu.c

diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851bu.c b/drivers/net/wireless/realtek/rtw89/rtw8851bu.c
new file mode 100644
index 000000000000..059b9b757698
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851bu.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) 2025  Realtek Corporation
+ */
+
+#include <linux/module.h>
+#include <linux/usb.h>
+#include "rtw8851b.h"
+#include "usb.h"
+
+static const struct rtw89_driver_info rtw89_8851bu_info = {
+	.chip = &rtw8851b_chip_info,
+	.variant = NULL,
+	.quirks = NULL,
+};
+
+static const struct usb_device_id rtw_8851bu_id_table[] = {
+	{ USB_DEVICE_AND_INTERFACE_INFO(0x0bda, 0xb851, 0xff, 0xff, 0xff),
+	  .driver_info = (kernel_ulong_t)&rtw89_8851bu_info },
+	{},
+};
+MODULE_DEVICE_TABLE(usb, rtw_8851bu_id_table);
+
+static struct usb_driver rtw_8851bu_driver = {
+	.name = KBUILD_MODNAME,
+	.id_table = rtw_8851bu_id_table,
+	.probe = rtw89_usb_probe,
+	.disconnect = rtw89_usb_disconnect,
+};
+module_usb_driver(rtw_8851bu_driver);
+
+MODULE_AUTHOR("Bitterblue Smith <rtl8821cerfe2@gmail.com>");
+MODULE_DESCRIPTION("Realtek 802.11ax wireless 8851BU driver");
+MODULE_LICENSE("Dual BSD/GPL");
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH rtw-next v1 13/13] wifi: rtw89: Enable the new USB modules
  2025-05-04 20:47 [PATCH rtw-next v1 00/13] wifi: rtw89: Add support for USB devices Bitterblue Smith
                   ` (11 preceding siblings ...)
  2025-05-04 20:54 ` [PATCH rtw-next v1 12/13] wifi: rtw89: Add rtw8851bu.c Bitterblue Smith
@ 2025-05-04 20:55 ` Bitterblue Smith
  2025-05-13  6:14   ` Ping-Ke Shih
  2025-05-13  6:22 ` [PATCH rtw-next v1 00/13] wifi: rtw89: Add support for USB devices Ping-Ke Shih
  2025-05-13  7:07 ` Ping-Ke Shih
  14 siblings, 1 reply; 47+ messages in thread
From: Bitterblue Smith @ 2025-05-04 20:55 UTC (permalink / raw)
  To: linux-wireless@vger.kernel.org; +Cc: Ping-Ke Shih

Enable compilation of the new rtw89_usb and rtw89_8851bu modules.

Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
---
 drivers/net/wireless/realtek/rtw89/Kconfig  | 14 ++++++++++++++
 drivers/net/wireless/realtek/rtw89/Makefile |  6 ++++++
 2 files changed, 20 insertions(+)

diff --git a/drivers/net/wireless/realtek/rtw89/Kconfig b/drivers/net/wireless/realtek/rtw89/Kconfig
index 205d7ecca7d7..bd180f3369c3 100644
--- a/drivers/net/wireless/realtek/rtw89/Kconfig
+++ b/drivers/net/wireless/realtek/rtw89/Kconfig
@@ -17,6 +17,9 @@ config RTW89_CORE
 config RTW89_PCI
 	tristate
 
+config RTW89_USB
+	tristate
+
 config RTW89_8851B
 	tristate
 
@@ -49,6 +52,17 @@ config RTW89_8851BE
 
 	  802.11ax PCIe wireless network (Wi-Fi 6) adapter
 
+config RTW89_8851BU
+	tristate "Realtek 8851BU USB wireless network (Wi-Fi 6) adapter"
+	depends on USB
+	select RTW89_CORE
+	select RTW89_USB
+	select RTW89_8851B
+	help
+	  Select this option will enable support for 8851BU chipset
+
+	  802.11ax USB wireless network (Wi-Fi 6) adapter
+
 config RTW89_8852AE
 	tristate "Realtek 8852AE PCI wireless network (Wi-Fi 6) adapter"
 	depends on PCI
diff --git a/drivers/net/wireless/realtek/rtw89/Makefile b/drivers/net/wireless/realtek/rtw89/Makefile
index c751013e811e..891e2d55c335 100644
--- a/drivers/net/wireless/realtek/rtw89/Makefile
+++ b/drivers/net/wireless/realtek/rtw89/Makefile
@@ -31,6 +31,9 @@ rtw89_8851b-objs := rtw8851b.o \
 obj-$(CONFIG_RTW89_8851BE) += rtw89_8851be.o
 rtw89_8851be-objs := rtw8851be.o
 
+obj-$(CONFIG_RTW89_8851BU) += rtw89_8851bu.o
+rtw89_8851bu-objs := rtw8851bu.o
+
 obj-$(CONFIG_RTW89_8852A) += rtw89_8852a.o
 rtw89_8852a-objs := rtw8852a.o \
 		    rtw8852a_table.o \
@@ -81,3 +84,6 @@ rtw89_core-$(CONFIG_RTW89_DEBUG) += debug.o
 obj-$(CONFIG_RTW89_PCI) += rtw89_pci.o
 rtw89_pci-y := pci.o pci_be.o
 
+obj-$(CONFIG_RTW89_USB) += rtw89_usb.o
+rtw89_usb-y := usb.o
+
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 47+ messages in thread

* RE: [PATCH rtw-next v1 01/13] wifi: rtw89: 8851b: Accept USB devices and load their MAC address
  2025-05-04 20:49 ` [PATCH rtw-next v1 01/13] wifi: rtw89: 8851b: Accept USB devices and load their MAC address Bitterblue Smith
@ 2025-05-13  2:46   ` Ping-Ke Shih
  0 siblings, 0 replies; 47+ messages in thread
From: Ping-Ke Shih @ 2025-05-13  2:46 UTC (permalink / raw)
  To: Bitterblue Smith, linux-wireless@vger.kernel.org

Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
> Make rtw8851b_read_efuse() accept USB devices and load the MAC address
> from the correct offset.
> 
> Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>

Acked-by: Ping-Ke Shih <pkshih@realtek.com>


^ permalink raw reply	[flat|nested] 47+ messages in thread

* RE: [PATCH rtw-next v1 02/13] wifi: rtw89: Get dle_mem via rtw89_hci_dle_mem()
  2025-05-04 20:49 ` [PATCH rtw-next v1 02/13] wifi: rtw89: Get dle_mem via rtw89_hci_dle_mem() Bitterblue Smith
@ 2025-05-13  2:51   ` Ping-Ke Shih
  2025-05-14  0:56   ` Ping-Ke Shih
  1 sibling, 0 replies; 47+ messages in thread
From: Ping-Ke Shih @ 2025-05-13  2:51 UTC (permalink / raw)
  To: Bitterblue Smith, linux-wireless@vger.kernel.org

Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
> Don't access dle_mem in get_dle_mem_cfg() directly. USB 2, USB 3, and
> SDIO will need different sets of values.
> 
> Rename dle_mem in struct rtw89_chip_info to dle_mem_pcie and get it
> via rtw89_hci_dle_mem() and rtw89_pci_ops_dle_mem().
> 
> Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>

Acked-by: Ping-Ke Shih <pkshih@realtek.com>




^ permalink raw reply	[flat|nested] 47+ messages in thread

* RE: [PATCH rtw-next v1 03/13] wifi: rtw89: Rename hfc_param_ini to hfc_param_ini_pcie
  2025-05-04 20:49 ` [PATCH rtw-next v1 03/13] wifi: rtw89: Rename hfc_param_ini to hfc_param_ini_pcie Bitterblue Smith
@ 2025-05-13  3:04   ` Ping-Ke Shih
  0 siblings, 0 replies; 47+ messages in thread
From: Ping-Ke Shih @ 2025-05-13  3:04 UTC (permalink / raw)
  To: Bitterblue Smith, linux-wireless@vger.kernel.org

Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
> Rename hfc_param_ini in struct rtw89_chip_info to hfc_param_ini_pcie.
> USB and SDIO will need different sets of values.
> 
> Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>

Acked-by: Ping-Ke Shih <pkshih@realtek.com>


^ permalink raw reply	[flat|nested] 47+ messages in thread

* RE: [PATCH rtw-next v1 04/13] wifi: rtw89: Add dle_mem_usb2 and dle_mem_usb3
  2025-05-04 20:50 ` [PATCH rtw-next v1 04/13] wifi: rtw89: Add dle_mem_usb2 and dle_mem_usb3 Bitterblue Smith
@ 2025-05-13  3:06   ` Ping-Ke Shih
  0 siblings, 0 replies; 47+ messages in thread
From: Ping-Ke Shih @ 2025-05-13  3:06 UTC (permalink / raw)
  To: Bitterblue Smith, linux-wireless@vger.kernel.org

Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
> Add new members dle_mem_usb2 and dle_mem_usb3 to struct rtw89_chip_info.
> For now initialise them only for RTL8851B.
> 
> Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
> ---

[..]

> @@ -1661,6 +1663,10 @@ const struct rtw89_mac_size_set rtw89_mac_size = {
>         .ple_size18 = {RTW89_PLE_PG_128, 2544, 16,},
>         /* 8852C PCIE SCC */
>         .ple_size19 = {RTW89_PLE_PG_128, 1904, 16,},
> +       /* 8852B USB2.0 SCC*/
> +       .ple_size32 = {RTW89_PLE_PG_128, 620, 20,},
> +       /* 8852B USB3.0 SCC*/

nit: space between "SCC" and "*/". Please also this rule apply to others in
this commit.

> +       .ple_size33 = {RTW89_PLE_PG_128, 632, 8,},
>         /* PCIE 64 */
>         .wde_qt0 = {3792, 196, 0, 107,},
>         .wde_qt0_v1 = {3302, 6, 0, 20,},

[...]


^ permalink raw reply	[flat|nested] 47+ messages in thread

* RE: [PATCH rtw-next v1 05/13] wifi: rtw89: Add hfc_param_ini_usb
  2025-05-04 20:51 ` [PATCH rtw-next v1 05/13] wifi: rtw89: Add hfc_param_ini_usb Bitterblue Smith
@ 2025-05-13  3:12   ` Ping-Ke Shih
  2025-05-25 21:55     ` Bitterblue Smith
  0 siblings, 1 reply; 47+ messages in thread
From: Ping-Ke Shih @ 2025-05-13  3:12 UTC (permalink / raw)
  To: Bitterblue Smith, linux-wireless@vger.kernel.org

Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
> Add hfc_param_ini_usb to struct rtw89_chip_info. For now initialise it
> only for RTL8851B.
> 
> Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
> ---

[...]


> +
> +static const struct rtw89_hfc_param_ini rtw8851b_hfc_param_ini_usb[] = {
> +       [RTW89_QTA_SCC] = {rtw8851b_hfc_chcfg_usb, &rtw8851b_hfc_pubcfg_usb,
> +                          &rtw8851b_hfc_preccfg_usb, RTW89_HCIFC_STF},

[RTW89_QTA_WOW] is missing. I'm not sure if current can handle this correctly.
Could you try to do WoWLAN with USB? At least, it shouldn't crash. 


> +       [RTW89_QTA_DLFW] = {NULL, NULL,
> +                          &rtw8851b_hfc_preccfg_usb, RTW89_HCIFC_STF},
> +       [RTW89_QTA_INVALID] = {NULL},
> +};
> +
>  static const struct rtw89_dle_mem rtw8851b_dle_mem_pcie[] = {
>         [RTW89_QTA_SCC] = {RTW89_QTA_SCC, &rtw89_mac_size.wde_size6,
>                            &rtw89_mac_size.ple_size6, &rtw89_mac_size.wde_qt6,

[...]


^ permalink raw reply	[flat|nested] 47+ messages in thread

* RE: [PATCH rtw-next v1 06/13] wifi: rtw89: Disable some power saving for USB
  2025-05-04 20:51 ` [PATCH rtw-next v1 06/13] wifi: rtw89: Disable some power saving for USB Bitterblue Smith
@ 2025-05-13  3:27   ` Ping-Ke Shih
  2025-05-25 21:57     ` Bitterblue Smith
  0 siblings, 1 reply; 47+ messages in thread
From: Ping-Ke Shih @ 2025-05-13  3:27 UTC (permalink / raw)
  To: Bitterblue Smith, linux-wireless@vger.kernel.org

Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
> Disable rtw89_ps_power_mode_change() and rtw89_mac_send_rpwm() for
> USB because they are called in atomic context and accessing hardware
> registers results in "scheduling while atomic" errors.

I feel rtw89_ps_power_mode_change() should be not in atomic context.
Please check this. 

> 
> Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
> ---
>  drivers/net/wireless/realtek/rtw89/mac.c | 3 +++
>  drivers/net/wireless/realtek/rtw89/ps.c  | 3 +++
>  2 files changed, 6 insertions(+)
> 
> diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
> index a316864ad137..1a03355b340f 100644
> --- a/drivers/net/wireless/realtek/rtw89/mac.c
> +++ b/drivers/net/wireless/realtek/rtw89/mac.c
> @@ -1338,6 +1338,9 @@ static void rtw89_mac_send_rpwm(struct rtw89_dev *rtwdev,
>  {
>         u16 request;
> 
> +       if (rtwdev->hci.type == RTW89_HCI_TYPE_USB)

I think SDIO devices have the same problems as USB, so I prefer to return
if "!= PCIE".

> +               return;
> +
>         spin_lock_bh(&rtwdev->rpwm_lock);
> 
>         request = rtw89_read16(rtwdev, R_AX_RPWM);
> diff --git a/drivers/net/wireless/realtek/rtw89/ps.c b/drivers/net/wireless/realtek/rtw89/ps.c
> index ac46a7baa00d..edff9f8e1016 100644
> --- a/drivers/net/wireless/realtek/rtw89/ps.c
> +++ b/drivers/net/wireless/realtek/rtw89/ps.c
> @@ -56,6 +56,9 @@ static void rtw89_ps_power_mode_change_with_hci(struct rtw89_dev *rtwdev,
> 
>  static void rtw89_ps_power_mode_change(struct rtw89_dev *rtwdev, bool enter)
>  {
> +       if (rtwdev->hci.type == RTW89_HCI_TYPE_USB)
> +               return;
> +
>         if (rtwdev->chip->low_power_hci_modes & BIT(rtwdev->ps_mode) &&
>             !test_bit(RTW89_FLAG_WOWLAN, rtwdev->flags))
>                 rtw89_ps_power_mode_change_with_hci(rtwdev, enter);
> --
> 2.49.0


^ permalink raw reply	[flat|nested] 47+ messages in thread

* RE: [PATCH rtw-next v1 07/13] wifi: rtw89: Add extra TX headroom for USB
  2025-05-04 20:51 ` [PATCH rtw-next v1 07/13] wifi: rtw89: Add extra TX headroom " Bitterblue Smith
@ 2025-05-13  3:28   ` Ping-Ke Shih
  0 siblings, 0 replies; 47+ messages in thread
From: Ping-Ke Shih @ 2025-05-13  3:28 UTC (permalink / raw)
  To: Bitterblue Smith, linux-wireless@vger.kernel.org

Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
> In the case of USB the TX descriptor is transmitted in the same buffer
> as the 802.11 frame, so add the required headroom.
> 
> Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>

Acked-by: Ping-Ke Shih <pkshih@realtek.com>



^ permalink raw reply	[flat|nested] 47+ messages in thread

* RE: [PATCH rtw-next v1 08/13] wifi: rtw89: Hide some errors when the device is unplugged
  2025-05-04 20:52 ` [PATCH rtw-next v1 08/13] wifi: rtw89: Hide some errors when the device is unplugged Bitterblue Smith
@ 2025-05-13  3:43   ` Ping-Ke Shih
  2025-05-25 21:58     ` Bitterblue Smith
  0 siblings, 1 reply; 47+ messages in thread
From: Ping-Ke Shih @ 2025-05-13  3:43 UTC (permalink / raw)
  To: Bitterblue Smith, linux-wireless@vger.kernel.org

Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
> A few unnecessary error messages are printed when the device is
> unplugged. "read swsi busy" in particular can appear ~1000 times when
> RTL8851BU is unplugged.
> 
> Add a new flag RTW89_FLAG_UNPLUGGED and print some error messages only
> when this flag is not set. The new USB driver will set the flag when
> the device is unplugged.
> 
> Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>

Acked-by: Ping-Ke Shih <pkshih@realtek.com>

[...]

> diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
> index 1a03355b340f..99f01fff90fe 100644
> --- a/drivers/net/wireless/realtek/rtw89/mac.c
> +++ b/drivers/net/wireless/realtek/rtw89/mac.c
> @@ -88,7 +88,7 @@ int rtw89_mac_write_lte(struct rtw89_dev *rtwdev, const u32 offset, u32 val)
> 
>         ret = read_poll_timeout(rtw89_read8, lte_ctrl, (lte_ctrl & BIT(5)) != 0,
>                                 50, 50000, false, rtwdev, R_AX_LTE_CTRL + 3);

For this case, timeout time is large enough for USB. But I'm surprising that
you don't need to adjust timeout time of read_poll_timeout() for USB devices, 
since USB is much slower than PCIE.

If sometime you need, I suggest this pattern (number is artificial): 

u64 rtw89_hci_timeout(rtwdev, to)
{
    if (USB 2)
        return max(to, 200); // I assume USB 2 is slower and 200 is enough for two times IO.
    else if (USB 3)
        return max(to, 100); // I assume USB 3 is faster than USB 2

    return to;
}

u64 to;

to = rtw89_hci_timeout(rtwdev, 30);

- read_poll_timeout(..., 1, 30, ...);
+ read_poll_timeout(..., 1, to, ...);



^ permalink raw reply	[flat|nested] 47+ messages in thread

* RE: [PATCH rtw-next v1 09/13] wifi: rtw89: Fix rtw89_mac_power_switch() for USB
  2025-05-04 20:52 ` [PATCH rtw-next v1 09/13] wifi: rtw89: Fix rtw89_mac_power_switch() for USB Bitterblue Smith
@ 2025-05-13  3:50   ` Ping-Ke Shih
  2025-05-25 21:58     ` Bitterblue Smith
  0 siblings, 1 reply; 47+ messages in thread
From: Ping-Ke Shih @ 2025-05-13  3:50 UTC (permalink / raw)
  To: Bitterblue Smith, linux-wireless@vger.kernel.org

Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
> Clear some bits in some registers in order to allow RTL8851BU to power
> on. Also tested with RTL8832BU and RTL8832CU.

I see mac_pwr_on_pcie_8851b() and mac_pwr_on_usb_8851b() at least in
vendor driver. If you use the power on/off functions for USB devices,
the problem may disappear. 

> 
> Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
> ---
>  drivers/net/wireless/realtek/rtw89/mac.c | 8 ++++++++
>  drivers/net/wireless/realtek/rtw89/reg.h | 1 +
>  2 files changed, 9 insertions(+)
> 
> diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
> index 99f01fff90fe..d3cf67dfabc9 100644
> --- a/drivers/net/wireless/realtek/rtw89/mac.c
> +++ b/drivers/net/wireless/realtek/rtw89/mac.c
> @@ -1458,6 +1458,14 @@ static int rtw89_mac_power_switch(struct rtw89_dev *rtwdev, bool on)
>         int ret;
>         u8 val;
> 
> +       if (rtwdev->hci.type == RTW89_HCI_TYPE_USB &&
> +           rtw89_read32_mask(rtwdev, R_AX_GPIO_MUXCFG, B_AX_BOOT_MODE)) {

Not prefer calling a function in if-statement. Suggest to add a function. 

> +               rtw89_write32_clr(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APFN_ONMAC);
> +               rtw89_write32_clr(rtwdev, R_AX_SYS_STATUS1, B_AX_AUTO_WLPON);
> +               rtw89_write32_clr(rtwdev, R_AX_GPIO_MUXCFG, B_AX_BOOT_MODE);
> +               rtw89_write32_clr(rtwdev, R_AX_RSV_CTRL, B_AX_R_DIS_PRST);
> +       }
> +
>         if (on) {
>                 cfg_seq = chip->pwr_on_seq;
>                 cfg_func = chip->ops->pwr_on_func;


^ permalink raw reply	[flat|nested] 47+ messages in thread

* RE: [PATCH rtw-next v1 10/13] wifi: rtw89: Add some definitions for USB
  2025-05-04 20:53 ` [PATCH rtw-next v1 10/13] wifi: rtw89: Add some definitions " Bitterblue Smith
@ 2025-05-13  3:52   ` Ping-Ke Shih
  0 siblings, 0 replies; 47+ messages in thread
From: Ping-Ke Shih @ 2025-05-13  3:52 UTC (permalink / raw)
  To: Bitterblue Smith, linux-wireless@vger.kernel.org

Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
> Add various register and bit definitions which will be used by the new
> USB driver.
> 
> Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>

Acked-by: Ping-Ke Shih <pkshih@realtek.com>



^ permalink raw reply	[flat|nested] 47+ messages in thread

* RE: [PATCH rtw-next v1 11/13] wifi: rtw89: Add usb.{c,h}
  2025-05-04 20:54 ` [PATCH rtw-next v1 11/13] wifi: rtw89: Add usb.{c,h} Bitterblue Smith
@ 2025-05-13  6:12   ` Ping-Ke Shih
  2025-05-25 22:03     ` Bitterblue Smith
  0 siblings, 1 reply; 47+ messages in thread
From: Ping-Ke Shih @ 2025-05-13  6:12 UTC (permalink / raw)
  To: Bitterblue Smith, linux-wireless@vger.kernel.org

Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
> Add very basic USB support. No TX/RX aggregation, no TX queues, no
> switching to USB 3 mode.
> 
> RTL8851BU and RTL8832BU work.
> 
> Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
> ---
>  drivers/net/wireless/realtek/rtw89/usb.c | 1030 ++++++++++++++++++++++
>  drivers/net/wireless/realtek/rtw89/usb.h |   61 ++
>  2 files changed, 1091 insertions(+)
>  create mode 100644 drivers/net/wireless/realtek/rtw89/usb.c
>  create mode 100644 drivers/net/wireless/realtek/rtw89/usb.h
> 
> diff --git a/drivers/net/wireless/realtek/rtw89/usb.c b/drivers/net/wireless/realtek/rtw89/usb.c
> new file mode 100644
> index 000000000000..6e8a544b352c
> --- /dev/null
> +++ b/drivers/net/wireless/realtek/rtw89/usb.c
> @@ -0,0 +1,1030 @@
> +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
> +/* Copyright(c) 2025  Realtek Corporation
> + */
> +
> +#include <linux/usb.h>
> +#include "debug.h"
> +#include "mac.h"
> +#include "reg.h"
> +#include "txrx.h"
> +#include "usb.h"
> +
> +static void rtw89_usb_vendorreq(struct rtw89_dev *rtwdev, u32 addr,
> +                               void *data, u16 len, u8 reqtype)
> +{
> +       struct rtw89_usb *rtwusb = rtw89_get_usb_priv(rtwdev);
> +       struct usb_device *udev = rtwusb->udev;
> +       unsigned int pipe;
> +       u16 value, index;
> +       int attempt, ret;
> +
> +       value = addr & 0x0000ffff;
> +       index = (addr & 0x00ff0000) >> 16;

u16_get_bits(addr, GENMASK(23, 16)) ?


> +
> +       mutex_lock(&rtwusb->vendor_req_mutex);

rtw89 takes wiphy_lock for control path. Is there any case more than 
one threads run at the same time?

> +
> +       for (attempt = 0; attempt < 10; attempt++) {
> +               *rtwusb->vendor_req_buf = 0;
> +
> +               if (reqtype == RTW89_USB_VENQT_READ) {
> +                       pipe = usb_rcvctrlpipe(udev, 0);
> +               } else { /* RTW89_USB_VENQT_WRITE */
> +                       pipe = usb_sndctrlpipe(udev, 0);
> +
> +                       memcpy(rtwusb->vendor_req_buf, data, len);

By "rtwusb->vendor_req_buf = kmalloc(sizeof(u32), GFP_KERNEL);", it seems like 
buffer size of vendor_req_buf is only 4 bytes. Is it enough space to do
memcpy()? Also, why not just a local variable ?


> +               }
> +
> +               ret = usb_control_msg(udev, pipe, RTW89_USB_VENQT, reqtype,
> +                                     value, index, rtwusb->vendor_req_buf,
> +                                     len, 500);
> +
> +               if (ret == len) { /* Success */
> +                       atomic_set(&rtwusb->continual_io_error, 0);
> +
> +                       if (reqtype == RTW89_USB_VENQT_READ)
> +                               memcpy(data, rtwusb->vendor_req_buf, len);
> +
> +                       break;
> +               }
> +
> +               if (ret == -ESHUTDOWN || ret == -ENODEV)
> +                       set_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags);
> +               else if (ret < 0)
> +                       rtw89_warn(rtwdev,
> +                                  "usb %s%u 0x%x fail ret=%d value=0x%x attempt=%d\n",
> +                                  reqtype == RTW89_USB_VENQT_READ ? "read" : "write",
> +                                  len * 8, addr, ret,
> +                                  le32_to_cpup(rtwusb->vendor_req_buf),
> +                                  attempt);
> +               else if (ret > 0 && reqtype == RTW89_USB_VENQT_READ)
> +                       memcpy(data, rtwusb->vendor_req_buf, len);
> +
> +               if (atomic_inc_return(&rtwusb->continual_io_error) > 4) {
> +                       set_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags);
> +                       break;
> +               }
> +       }
> +
> +       mutex_unlock(&rtwusb->vendor_req_mutex);
> +}
> +
> +static u32 rtw89_usb_read_cmac(struct rtw89_dev *rtwdev, u32 addr)
> +{
> +       u32 addr32, val32, shift;
> +       __le32 data = 0;
> +       int count;
> +
> +       addr32 = addr & ~0x3;
> +       shift = (addr & 0x3) * 8;
> +
> +       for (count = 0; ; count++) {
> +               rtw89_usb_vendorreq(rtwdev, addr32, &data, 4,
> +                                   RTW89_USB_VENQT_READ);
> +
> +               val32 = le32_to_cpu(data);
> +

no empty line between assignment and immediate checking. 

> +               if (val32 != RTW89_R32_DEAD)
> +                       break;
> +
> +               if (count >= MAC_REG_POOL_COUNT) {
> +                       rtw89_warn(rtwdev, "%s: addr %#x = %#x\n",
> +                                  __func__, addr32, val32);
> +                       val32 = RTW89_R32_DEAD;
> +                       break;
> +               }
> +
> +               rtw89_write32(rtwdev, R_AX_CK_EN, B_AX_CMAC_ALLCKEN);
> +       }
> +
> +       return val32 >> shift;
> +}

[...]

> +static void rtw89_usb_write_port_complete(struct urb *urb)
> +{
> +       struct rtw89_usb_tx_ctrl_block *txcb = urb->context;
> +       struct rtw89_dev *rtwdev = txcb->rtwdev;
> +       struct ieee80211_tx_info *info;
> +       struct sk_buff *skb;
> +
> +       while (true) {

Is it possible that more than one skb are in txcb->tx_ack_queue?
With USB aggregation afterword, it will become possible?

> +               skb = skb_dequeue(&txcb->tx_ack_queue);
> +               if (!skb)
> +                       break;
> +
> +               info = IEEE80211_SKB_CB(skb);
> +               ieee80211_tx_info_clear_status(info);
> +
> +               if (urb->status == 0) {
> +                       if (info->flags & IEEE80211_TX_CTL_NO_ACK)
> +                               info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED;
> +                       else
> +                               info->flags |= IEEE80211_TX_STAT_ACK;
> +               }
> +
> +               ieee80211_tx_status_irqsafe(rtwdev->hw, skb);
> +       }
> +
> +       switch (urb->status) {
> +       case 0:
> +       case -EPIPE:
> +       case -EPROTO:
> +       case -EINPROGRESS:
> +       case -ENOENT:
> +       case -ECONNRESET:
> +               break;
> +       default:
> +               set_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags);
> +               break;
> +       }
> +
> +       kfree(txcb);
> +       usb_free_urb(urb);
> +}
> +

[...]

> +
> +static void rtw89_usb_read_port_complete(struct urb *urb);

Move to beginning of this file. 

> +
> +static void rtw89_usb_rx_resubmit(struct rtw89_usb *rtwusb,
> +                                 struct rtw89_usb_rx_ctrl_block *rxcb,
> +                                 gfp_t gfp)
> +{
> +       struct rtw89_dev *rtwdev = rtwusb->rtwdev;
> +       struct sk_buff *rx_skb;
> +       int error;

Why not 'int ret' in commom? 

[...]

> +
> +static void rtw89_usb_cancel_rx_bufs(struct rtw89_usb *rtwusb)
> +{
> +       struct rtw89_usb_rx_ctrl_block *rxcb;
> +       int i;
> +
> +       for (i = 0; i < RTW89_USB_RXCB_NUM; i++) {
> +               rxcb = &rtwusb->rx_cb[i];
> +               usb_kill_urb(rxcb->rx_urb);

rtw89_usb_disconnect() calls rtw89_usb_cancel_rx_bufs() and then call
rtw89_usb_free_rx_bufs(). Is it a problem that usb_kill_urb() is called twice?

> +       }
> +}
> +
> +static void rtw89_usb_free_rx_bufs(struct rtw89_usb *rtwusb)
> +{
> +       struct rtw89_usb_rx_ctrl_block *rxcb;
> +       int i;
> +
> +       for (i = 0; i < RTW89_USB_RXCB_NUM; i++) {
> +               rxcb = &rtwusb->rx_cb[i];
> +
> +               usb_kill_urb(rxcb->rx_urb);
> +               usb_free_urb(rxcb->rx_urb);
> +       }
> +}
> +

[...]

> +
> +static int rtw89_usb_ops_mac_lv1_rcvy(struct rtw89_dev *rtwdev,
> +                                     enum rtw89_lv1_rcvy_step step)
> +{
> +       u32 reg, mask;
> +
> +       switch (rtwdev->chip->chip_id) {
> +       case RTL8851B:
> +       case RTL8852A:
> +       case RTL8852B:
> +               reg = R_AX_USB_WLAN0_1;
> +               mask = B_AX_USBRX_RST | B_AX_USBTX_RST;
> +               break;
> +       case RTL8852C:
> +               reg = R_AX_USB_WLAN0_1_V1;
> +               mask = B_AX_USBRX_RST_V1 | B_AX_USBTX_RST_V1;
> +               break;
> +       default:
> +               rtw89_err(rtwdev, "%s: fix me\n", __func__);
> +               return -EOPNOTSUPP;
> +       }
> +
> +       switch (step) {
> +       case RTW89_LV1_RCVY_STEP_1:
> +               rtw89_write32_set(rtwdev, reg, mask);
> +
> +               msleep(30);
> +

maybe no need this empty line.

> +               break;
> +       case RTW89_LV1_RCVY_STEP_2:
> +               rtw89_write32_clr(rtwdev, reg, mask);
> +

no need this empty line.

> +               break;
> +       default:
> +               return -EINVAL;
> +       }
> +
> +       return 0;
> +}
> +

[...]

> +static int rtw89_usb_intf_init(struct rtw89_dev *rtwdev,
> +                              struct usb_interface *intf)
> +{
> +       struct rtw89_usb *rtwusb = rtw89_get_usb_priv(rtwdev);
> +       int ret;
> +
> +       ret = rtw89_usb_parse(rtwdev, intf);
> +       if (ret)
> +               return ret;
> +
> +       rtwusb->vendor_req_buf = kmalloc(sizeof(u32), GFP_KERNEL);

I mentioned this allocation before. 

> +       if (!rtwusb->vendor_req_buf)
> +               return -ENOMEM;
> +
> +       rtwusb->udev = usb_get_dev(interface_to_usbdev(intf));
> +
> +       usb_set_intfdata(intf, rtwdev->hw);
> +
> +       SET_IEEE80211_DEV(rtwdev->hw, &intf->dev);
> +
> +       mutex_init(&rtwusb->vendor_req_mutex);
> +
> +       return 0;
> +}
> +

[...]

> diff --git a/drivers/net/wireless/realtek/rtw89/usb.h b/drivers/net/wireless/realtek/rtw89/usb.h
> new file mode 100644
> index 000000000000..86caae1b9d0b
> --- /dev/null
> +++ b/drivers/net/wireless/realtek/rtw89/usb.h
> @@ -0,0 +1,61 @@
> +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
> +/* Copyright(c) 2025  Realtek Corporation
> + */
> +
> +#ifndef __RTW89_USB_H__
> +#define __RTW89_USB_H__
> +

[...]

> +
> +static inline struct rtw89_usb *rtw89_get_usb_priv(struct rtw89_dev *rtwdev)

Not sure if it is worth of this wrapper. Or just rtw89_usb_priv()? 

> +{
> +       return (struct rtw89_usb *)rtwdev->priv;
> +}
> +
> +int rtw89_usb_probe(struct usb_interface *intf,
> +                   const struct usb_device_id *id);
> +void rtw89_usb_disconnect(struct usb_interface *intf);
> +
> +#endif
> --
> 2.49.0


^ permalink raw reply	[flat|nested] 47+ messages in thread

* RE: [PATCH rtw-next v1 12/13] wifi: rtw89: Add rtw8851bu.c
  2025-05-04 20:54 ` [PATCH rtw-next v1 12/13] wifi: rtw89: Add rtw8851bu.c Bitterblue Smith
@ 2025-05-13  6:14   ` Ping-Ke Shih
  0 siblings, 0 replies; 47+ messages in thread
From: Ping-Ke Shih @ 2025-05-13  6:14 UTC (permalink / raw)
  To: Bitterblue Smith, linux-wireless@vger.kernel.org

Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
> This is the entry point for the new rtw89_8851bu module.
> 
> Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>

Acked-by: Ping-Ke Shih <pkshih@realtek.com>


^ permalink raw reply	[flat|nested] 47+ messages in thread

* RE: [PATCH rtw-next v1 13/13] wifi: rtw89: Enable the new USB modules
  2025-05-04 20:55 ` [PATCH rtw-next v1 13/13] wifi: rtw89: Enable the new USB modules Bitterblue Smith
@ 2025-05-13  6:14   ` Ping-Ke Shih
  0 siblings, 0 replies; 47+ messages in thread
From: Ping-Ke Shih @ 2025-05-13  6:14 UTC (permalink / raw)
  To: Bitterblue Smith, linux-wireless@vger.kernel.org

Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
> Enable compilation of the new rtw89_usb and rtw89_8851bu modules.
> 
> Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>

Acked-by: Ping-Ke Shih <pkshih@realtek.com>



^ permalink raw reply	[flat|nested] 47+ messages in thread

* RE: [PATCH rtw-next v1 00/13] wifi: rtw89: Add support for USB devices
  2025-05-04 20:47 [PATCH rtw-next v1 00/13] wifi: rtw89: Add support for USB devices Bitterblue Smith
                   ` (12 preceding siblings ...)
  2025-05-04 20:55 ` [PATCH rtw-next v1 13/13] wifi: rtw89: Enable the new USB modules Bitterblue Smith
@ 2025-05-13  6:22 ` Ping-Ke Shih
  2025-05-13  7:07 ` Ping-Ke Shih
  14 siblings, 0 replies; 47+ messages in thread
From: Ping-Ke Shih @ 2025-05-13  6:22 UTC (permalink / raw)
  To: Bitterblue Smith, linux-wireless@vger.kernel.org

Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
> 
> Add support for USB devices, starting with just RTL8851BU.

Thanks for your work!!

> RTL8832BU/RTL8852BU can be supported easily later. RTL8832CU/RTL8852CU
> can be supported as well, but it keeps losing the connection.
> 
> This is based on rtw88_usb and the official rtl8851bu driver
> v1.19.10-70-g84e35c28d.20231019 from here:
> https://github.com/fofajardo/rtl8851bu
> 
> I didn't test with any PCI devices.

I tested RTL8851BE. It works as usual.


^ permalink raw reply	[flat|nested] 47+ messages in thread

* RE: [PATCH rtw-next v1 00/13] wifi: rtw89: Add support for USB devices
  2025-05-04 20:47 [PATCH rtw-next v1 00/13] wifi: rtw89: Add support for USB devices Bitterblue Smith
                   ` (13 preceding siblings ...)
  2025-05-13  6:22 ` [PATCH rtw-next v1 00/13] wifi: rtw89: Add support for USB devices Ping-Ke Shih
@ 2025-05-13  7:07 ` Ping-Ke Shih
  2025-05-25 22:03   ` Bitterblue Smith
  14 siblings, 1 reply; 47+ messages in thread
From: Ping-Ke Shih @ 2025-05-13  7:07 UTC (permalink / raw)
  To: Bitterblue Smith, linux-wireless@vger.kernel.org

Ping-Ke Shih wrote:
> Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
> >
> > Add support for USB devices, starting with just RTL8851BU.
> 
> Thanks for your work!!

Have you also tested AP mode? If not, please add a patch to disable it
temporarily as a transition solution, like rtw88. 

> 
> > RTL8832BU/RTL8852BU can be supported easily later. RTL8832CU/RTL8852CU
> > can be supported as well, but it keeps losing the connection.
> >
> > This is based on rtw88_usb and the official rtl8851bu driver
> > v1.19.10-70-g84e35c28d.20231019 from here:
> > https://github.com/fofajardo/rtl8851bu
> >
> > I didn't test with any PCI devices.
> 
> I tested RTL8851BE. It works as usual.


^ permalink raw reply	[flat|nested] 47+ messages in thread

* RE: [PATCH rtw-next v1 02/13] wifi: rtw89: Get dle_mem via rtw89_hci_dle_mem()
  2025-05-04 20:49 ` [PATCH rtw-next v1 02/13] wifi: rtw89: Get dle_mem via rtw89_hci_dle_mem() Bitterblue Smith
  2025-05-13  2:51   ` Ping-Ke Shih
@ 2025-05-14  0:56   ` Ping-Ke Shih
  2025-05-25 22:04     ` Bitterblue Smith
  1 sibling, 1 reply; 47+ messages in thread
From: Ping-Ke Shih @ 2025-05-14  0:56 UTC (permalink / raw)
  To: Bitterblue Smith, linux-wireless@vger.kernel.org

Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
> Don't access dle_mem in get_dle_mem_cfg() directly. USB 2, USB 3, and
> SDIO will need different sets of values.
> 
> Rename dle_mem in struct rtw89_chip_info to dle_mem_pcie and get it
> via rtw89_hci_dle_mem() and rtw89_pci_ops_dle_mem().
> 
> Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
> ---
>  drivers/net/wireless/realtek/rtw89/core.h      | 10 +++++++++-
>  drivers/net/wireless/realtek/rtw89/mac.c       |  2 +-
>  drivers/net/wireless/realtek/rtw89/pci.c       |  8 ++++++++
>  drivers/net/wireless/realtek/rtw89/rtw8851b.c  |  2 +-
>  drivers/net/wireless/realtek/rtw89/rtw8852a.c  |  2 +-
>  drivers/net/wireless/realtek/rtw89/rtw8852b.c  |  2 +-
>  drivers/net/wireless/realtek/rtw89/rtw8852bt.c |  2 +-
>  drivers/net/wireless/realtek/rtw89/rtw8852c.c  |  2 +-
>  drivers/net/wireless/realtek/rtw89/rtw8922a.c  |  2 +-
>  9 files changed, 24 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
> index be1259cfa712..afcf0353a625 100644
> --- a/drivers/net/wireless/realtek/rtw89/core.h
> +++ b/drivers/net/wireless/realtek/rtw89/core.h
> @@ -3579,6 +3579,8 @@ struct rtw89_hci_ops {
>         void (*disable_intr)(struct rtw89_dev *rtwdev);
>         void (*enable_intr)(struct rtw89_dev *rtwdev);
>         int (*rst_bdram)(struct rtw89_dev *rtwdev);

an empty line

> +       const struct rtw89_dle_mem *(*dle_mem)(struct rtw89_dev *rtwdev,
> +                                              u8 qta_mode);
>  };
> 
>  struct rtw89_hci_info {
> @@ -4271,7 +4273,7 @@ struct rtw89_chip_info {
>         bool dis_2g_40m_ul_ofdma;
>         u32 rsvd_ple_ofst;
>         const struct rtw89_hfc_param_ini *hfc_param_ini;
> -       const struct rtw89_dle_mem *dle_mem;
> +       const struct rtw89_dle_mem *dle_mem_pcie;

I reconsider if this can be an array with a new enum = {PCIE, USB2, USB3, SDIO}
stored in hal->hci_dle_mem_type. Then, consumers can just access it via
chip->dle_mem[hal->hci_dle_mem_type][quota]. But, I'm not sure if USB
subsystem can notify driver when USB speed is changed. 

This is a thought to simply the struct definition. 

>         u8 wde_qempty_acq_grpnum;
>         u8 wde_qempty_mgq_grpsel;
>         u32 rf_base_addr[2];
> @@ -6146,6 +6148,12 @@ static inline void rtw89_hci_clear(struct rtw89_dev *rtwdev, struct pci_dev *pde
>                 rtwdev->hci.ops->clear(rtwdev, pdev);
>  }
> 
> +static inline const
> +struct rtw89_dle_mem *rtw89_hci_dle_mem(struct rtw89_dev *rtwdev, u8 qta_mode)
> +{
> +       return rtwdev->hci.ops->dle_mem(rtwdev, qta_mode);
> +}
> +
>  static inline
>  struct rtw89_tx_skb_data *RTW89_TX_SKB_CB(struct sk_buff *skb)
>  {
> diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
> index 592fbb6d2728..77d35db3e133 100644
> --- a/drivers/net/wireless/realtek/rtw89/mac.c
> +++ b/drivers/net/wireless/realtek/rtw89/mac.c
> @@ -1719,7 +1719,7 @@ static const struct rtw89_dle_mem *get_dle_mem_cfg(struct rtw89_dev *rtwdev,
>         struct rtw89_mac_info *mac = &rtwdev->mac;
>         const struct rtw89_dle_mem *cfg;
> 
> -       cfg = &rtwdev->chip->dle_mem[mode];
> +       cfg = rtw89_hci_dle_mem(rtwdev, mode);
>         if (!cfg)
>                 return NULL;
> 
> diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c
> index c2fe5a898dc7..1dec603012ba 100644
> --- a/drivers/net/wireless/realtek/rtw89/pci.c
> +++ b/drivers/net/wireless/realtek/rtw89/pci.c
> @@ -4341,6 +4341,13 @@ static int __maybe_unused rtw89_pci_resume(struct device *dev)
>  SIMPLE_DEV_PM_OPS(rtw89_pm_ops, rtw89_pci_suspend, rtw89_pci_resume);
>  EXPORT_SYMBOL(rtw89_pm_ops);
> 
> +static const
> +struct rtw89_dle_mem *rtw89_pci_ops_dle_mem(struct rtw89_dev *rtwdev,
> +                                           u8 qta_mode)
> +{
> +       return &rtwdev->chip->dle_mem_pcie[qta_mode];
> +}
> +
>  const struct rtw89_pci_gen_def rtw89_pci_gen_ax = {
>         .isr_rdu = B_AX_RDU_INT,
>         .isr_halt_c2h = B_AX_HALT_C2H_INT_EN,
> @@ -4413,6 +4420,7 @@ static const struct rtw89_hci_ops rtw89_pci_ops = {
>         .disable_intr   = rtw89_pci_disable_intr_lock,
>         .enable_intr    = rtw89_pci_enable_intr_lock,
>         .rst_bdram      = rtw89_pci_reset_bdram,

an empty line

> +       .dle_mem        = rtw89_pci_ops_dle_mem,
>  };
> 

[...]



^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH rtw-next v1 05/13] wifi: rtw89: Add hfc_param_ini_usb
  2025-05-13  3:12   ` Ping-Ke Shih
@ 2025-05-25 21:55     ` Bitterblue Smith
  2025-05-26  1:51       ` Ping-Ke Shih
  0 siblings, 1 reply; 47+ messages in thread
From: Bitterblue Smith @ 2025-05-25 21:55 UTC (permalink / raw)
  To: Ping-Ke Shih, linux-wireless@vger.kernel.org

On 13/05/2025 06:12, Ping-Ke Shih wrote:
> Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
>> Add hfc_param_ini_usb to struct rtw89_chip_info. For now initialise it
>> only for RTL8851B.
>>
>> Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
>> ---
> 
> [...]
> 
> 
>> +
>> +static const struct rtw89_hfc_param_ini rtw8851b_hfc_param_ini_usb[] = {
>> +       [RTW89_QTA_SCC] = {rtw8851b_hfc_chcfg_usb, &rtw8851b_hfc_pubcfg_usb,
>> +                          &rtw8851b_hfc_preccfg_usb, RTW89_HCIFC_STF},
> 
> [RTW89_QTA_WOW] is missing. I'm not sure if current can handle this correctly.
> Could you try to do WoWLAN with USB? At least, it shouldn't crash. 
> 

RTW89_QTA_WOW is missing because I didn't find an equivalent in
enum mac_ax_qta_mode in the vendor driver.

I enabled WOWLAN with this command:

iw phy0 wowlan enable disconnect

Then I put the computer to sleep (suspend to RAM). There was no crash,
just some error messages. The computer went to sleep and woke up without
any other problems. Of course it didn't stay connected to the access
point during sleep.

May 23 20:19:46 ideapad2 kernel: rtw89_8851bu 1-2:1.2: qta mode unmatch!
May 23 20:19:47 ideapad2 kernel: rtw89_8851bu 1-2:1.2: [ERR]get_dle_mem_cfg
May 23 20:19:47 ideapad2 kernel: rtw89_8851bu 1-2:1.2: [ERR]patch rx qta -22
May 23 20:19:47 ideapad2 kernel: rtw89_8851bu 1-2:1.2: failed to config mac
May 23 20:19:47 ideapad2 kernel: rtw89_8851bu 1-2:1.2: wow: failed to enable trx_post
May 23 20:19:47 ideapad2 kernel: rtw89_8851bu 1-2:1.2: failed to enable wow
May 23 20:19:47 ideapad2 kernel: rtw89_8851bu 1-2:1.2: failed to suspend for wow -22

That was without RTW89_QTA_WOW.

Then I tried to copy RTW89_QTA_SCC in rtw8851b_hfc_param_ini_usb and
rtw8851b_dle_mem_usb2. With that I think it was able to upload the WOW
firmware and it stayed connected to the access point, but something
didn't let the computer go to sleep. It sat there for several minutes
with a black screen, the power LED on, and connected to the access
point (but without an IP address), until I clicked the "Disconnect"
button in the access point's web interface to disconnect this station.
That's when the computer finally went to sleep.

So WOWLAN with RTL8851BU needs more work.

> 
>> +       [RTW89_QTA_DLFW] = {NULL, NULL,
>> +                          &rtw8851b_hfc_preccfg_usb, RTW89_HCIFC_STF},
>> +       [RTW89_QTA_INVALID] = {NULL},
>> +};
>> +
>>  static const struct rtw89_dle_mem rtw8851b_dle_mem_pcie[] = {
>>         [RTW89_QTA_SCC] = {RTW89_QTA_SCC, &rtw89_mac_size.wde_size6,
>>                            &rtw89_mac_size.ple_size6, &rtw89_mac_size.wde_qt6,
> 
> [...]
> 


^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH rtw-next v1 06/13] wifi: rtw89: Disable some power saving for USB
  2025-05-13  3:27   ` Ping-Ke Shih
@ 2025-05-25 21:57     ` Bitterblue Smith
  2025-05-26  2:36       ` Ping-Ke Shih
  0 siblings, 1 reply; 47+ messages in thread
From: Bitterblue Smith @ 2025-05-25 21:57 UTC (permalink / raw)
  To: Ping-Ke Shih, linux-wireless@vger.kernel.org

On 13/05/2025 06:27, Ping-Ke Shih wrote:
> Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
>> Disable rtw89_ps_power_mode_change() and rtw89_mac_send_rpwm() for
>> USB because they are called in atomic context and accessing hardware
>> registers results in "scheduling while atomic" errors.
> 
> I feel rtw89_ps_power_mode_change() should be not in atomic context.
> Please check this. 
> 

I think you're right, only rtw89_mac_send_rpwm() is called in atomic
context. rtw89_ps_power_mode_change() is disabled for other reasons:

1) It calls rtw89_mac_power_mode_change(), which prints errors when
rtw89_mac_send_rpwm() is disabled.

2) With RTL8852CU it calls rtw89_ps_power_mode_change_with_hci()
which calls napi_schedule(). That results in dereferencing a null
pointer.

>>
>> Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
>> ---
>>  drivers/net/wireless/realtek/rtw89/mac.c | 3 +++
>>  drivers/net/wireless/realtek/rtw89/ps.c  | 3 +++
>>  2 files changed, 6 insertions(+)
>>
>> diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
>> index a316864ad137..1a03355b340f 100644
>> --- a/drivers/net/wireless/realtek/rtw89/mac.c
>> +++ b/drivers/net/wireless/realtek/rtw89/mac.c
>> @@ -1338,6 +1338,9 @@ static void rtw89_mac_send_rpwm(struct rtw89_dev *rtwdev,
>>  {
>>         u16 request;
>>
>> +       if (rtwdev->hci.type == RTW89_HCI_TYPE_USB)
> 
> I think SDIO devices have the same problems as USB, so I prefer to return
> if "!= PCIE".
> 
>> +               return;
>> +
>>         spin_lock_bh(&rtwdev->rpwm_lock);
>>
>>         request = rtw89_read16(rtwdev, R_AX_RPWM);
>> diff --git a/drivers/net/wireless/realtek/rtw89/ps.c b/drivers/net/wireless/realtek/rtw89/ps.c
>> index ac46a7baa00d..edff9f8e1016 100644
>> --- a/drivers/net/wireless/realtek/rtw89/ps.c
>> +++ b/drivers/net/wireless/realtek/rtw89/ps.c
>> @@ -56,6 +56,9 @@ static void rtw89_ps_power_mode_change_with_hci(struct rtw89_dev *rtwdev,
>>
>>  static void rtw89_ps_power_mode_change(struct rtw89_dev *rtwdev, bool enter)
>>  {
>> +       if (rtwdev->hci.type == RTW89_HCI_TYPE_USB)
>> +               return;
>> +
>>         if (rtwdev->chip->low_power_hci_modes & BIT(rtwdev->ps_mode) &&
>>             !test_bit(RTW89_FLAG_WOWLAN, rtwdev->flags))
>>                 rtw89_ps_power_mode_change_with_hci(rtwdev, enter);
>> --
>> 2.49.0
> 


^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH rtw-next v1 08/13] wifi: rtw89: Hide some errors when the device is unplugged
  2025-05-13  3:43   ` Ping-Ke Shih
@ 2025-05-25 21:58     ` Bitterblue Smith
  0 siblings, 0 replies; 47+ messages in thread
From: Bitterblue Smith @ 2025-05-25 21:58 UTC (permalink / raw)
  To: Ping-Ke Shih, linux-wireless@vger.kernel.org

On 13/05/2025 06:43, Ping-Ke Shih wrote:
> Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
>> A few unnecessary error messages are printed when the device is
>> unplugged. "read swsi busy" in particular can appear ~1000 times when
>> RTL8851BU is unplugged.
>>
>> Add a new flag RTW89_FLAG_UNPLUGGED and print some error messages only
>> when this flag is not set. The new USB driver will set the flag when
>> the device is unplugged.
>>
>> Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
> 
> Acked-by: Ping-Ke Shih <pkshih@realtek.com>
> 
> [...]
> 
>> diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
>> index 1a03355b340f..99f01fff90fe 100644
>> --- a/drivers/net/wireless/realtek/rtw89/mac.c
>> +++ b/drivers/net/wireless/realtek/rtw89/mac.c
>> @@ -88,7 +88,7 @@ int rtw89_mac_write_lte(struct rtw89_dev *rtwdev, const u32 offset, u32 val)
>>
>>         ret = read_poll_timeout(rtw89_read8, lte_ctrl, (lte_ctrl & BIT(5)) != 0,
>>                                 50, 50000, false, rtwdev, R_AX_LTE_CTRL + 3);
> 
> For this case, timeout time is large enough for USB. But I'm surprising that
> you don't need to adjust timeout time of read_poll_timeout() for USB devices, 
> since USB is much slower than PCIE.
> 

I don't know, it seems fine.

> If sometime you need, I suggest this pattern (number is artificial): 
> 
> u64 rtw89_hci_timeout(rtwdev, to)
> {
>     if (USB 2)
>         return max(to, 200); // I assume USB 2 is slower and 200 is enough for two times IO.
>     else if (USB 3)
>         return max(to, 100); // I assume USB 3 is faster than USB 2
> 
>     return to;
> }
> 
> u64 to;
> 
> to = rtw89_hci_timeout(rtwdev, 30);
> 
> - read_poll_timeout(..., 1, 30, ...);
> + read_poll_timeout(..., 1, to, ...);
> 
> 


^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH rtw-next v1 09/13] wifi: rtw89: Fix rtw89_mac_power_switch() for USB
  2025-05-13  3:50   ` Ping-Ke Shih
@ 2025-05-25 21:58     ` Bitterblue Smith
  2025-05-26  2:45       ` Ping-Ke Shih
  0 siblings, 1 reply; 47+ messages in thread
From: Bitterblue Smith @ 2025-05-25 21:58 UTC (permalink / raw)
  To: Ping-Ke Shih, linux-wireless@vger.kernel.org

On 13/05/2025 06:50, Ping-Ke Shih wrote:
> Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
>> Clear some bits in some registers in order to allow RTL8851BU to power
>> on. Also tested with RTL8832BU and RTL8832CU.
> 
> I see mac_pwr_on_pcie_8851b() and mac_pwr_on_usb_8851b() at least in
> vendor driver. If you use the power on/off functions for USB devices,
> the problem may disappear. 
> 

I modified rtw8851b_pwr_on_func() and rtw8851b_pwr_off_func() to match
mac_pwr_on_usb_8851b() and mac_pwr_off_usb_8851b(). It wasn't enough.
Without this patch the firmware upload still fails:

[ 1238.299960] rtw89_8851bu 1-2:1.2: Firmware version 0.29.41.3 (65cefb31), cmd version 0, type 5                                                                          
[ 1238.299970] rtw89_8851bu 1-2:1.2: Firmware version 0.29.41.3 (65cefb31), cmd version 0, type 3                                                                          
[ 1238.523187] Bluetooth: hci1: RTL: fw version 0x048ad230                                                                                                                 
[ 1238.607110] Bluetooth: hci1: AOSP extensions version v1.00                                                                                                              
[ 1238.622986] Bluetooth: MGMT ver 1.23                                                                                                                                    
[ 1388.109364] rtw89_8851bu 1-2:1.2: [ERR]H2C path ready                                                                                                                   
[ 1388.109751] rtw89_8851bu 1-2:1.2: [ERR]fwdl 0x1E0 = 0xc1                                                                                                                
[ 1388.110115] rtw89_8851bu 1-2:1.2: [ERR]fwdl 0x83F0 = 0x120090                                                                                                           
[ 1388.111615] rtw89_8851bu 1-2:1.2: [ERR]fw PC = 0xb890cd07                                                                                                               
[ 1388.111984] rtw89_8851bu 1-2:1.2: [ERR]fw PC = 0xb890cde5                                                                                                               
[ 1388.112358] rtw89_8851bu 1-2:1.2: [ERR]fw PC = 0xb890cd2b                                                                                                               
[ 1388.112740] rtw89_8851bu 1-2:1.2: [ERR]fw PC = 0xb890ef05                                                                                                               
[ 1388.113110] rtw89_8851bu 1-2:1.2: [ERR]fw PC = 0xb890cd2b                                                                                                               
[ 1388.113510] rtw89_8851bu 1-2:1.2: [ERR]fw PC = 0xb890cce3                                                                                                               
[ 1388.113868] rtw89_8851bu 1-2:1.2: [ERR]fw PC = 0xb890cce3                                                                                                               
[ 1388.114234] rtw89_8851bu 1-2:1.2: [ERR]fw PC = 0xb890cded                         
[ 1388.114693] rtw89_8851bu 1-2:1.2: [ERR]fw PC = 0xb890cce3                                                                                                               
[ 1388.114986] rtw89_8851bu 1-2:1.2: [ERR]fw PC = 0xb890cce3                                                                                                               
[ 1388.115358] rtw89_8851bu 1-2:1.2: [ERR]fw PC = 0xb890cde9                                                                                                               
[ 1388.115735] rtw89_8851bu 1-2:1.2: [ERR]fw PC = 0xb890cce3                                                                                                               
[ 1388.116109] rtw89_8851bu 1-2:1.2: [ERR]fw PC = 0xb890cce3                                                                                                               
[ 1388.116480] rtw89_8851bu 1-2:1.2: [ERR]fw PC = 0xb89957b3                                                                                                               
[ 1388.116867] rtw89_8851bu 1-2:1.2: [ERR]fw PC = 0xb890cce3                                                                                                               

(By the way, 150 seconds is a long time and this is just the first batch
of error messages. There are at least two more like the above and each
takes another 150 seconds to appear. Things freeze:

[ 1475.693454] INFO: task systemd-journal:284 blocked for more than 122 seconds.
[ 1475.693750] INFO: task kded6:853 blocked for more than 122 seconds.
[ 1598.573772] INFO: task upowerd:1021 blocked for more than 122 seconds.

I haven't figured out how to fix this long delay yet.)

>>
>> Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
>> ---
>>  drivers/net/wireless/realtek/rtw89/mac.c | 8 ++++++++
>>  drivers/net/wireless/realtek/rtw89/reg.h | 1 +
>>  2 files changed, 9 insertions(+)
>>
>> diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
>> index 99f01fff90fe..d3cf67dfabc9 100644
>> --- a/drivers/net/wireless/realtek/rtw89/mac.c
>> +++ b/drivers/net/wireless/realtek/rtw89/mac.c
>> @@ -1458,6 +1458,14 @@ static int rtw89_mac_power_switch(struct rtw89_dev *rtwdev, bool on)
>>         int ret;
>>         u8 val;
>>
>> +       if (rtwdev->hci.type == RTW89_HCI_TYPE_USB &&
>> +           rtw89_read32_mask(rtwdev, R_AX_GPIO_MUXCFG, B_AX_BOOT_MODE)) {
> 
> Not prefer calling a function in if-statement. Suggest to add a function. 
> 

Do you mean add a variable?

	boot_mode = rtw89_read32_mask(rtwdev, R_AX_GPIO_MUXCFG, B_AX_BOOT_MODE);

	if (rtwdev->hci.type == RTW89_HCI_TYPE_USB && boot_mode) {


>> +               rtw89_write32_clr(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APFN_ONMAC);
>> +               rtw89_write32_clr(rtwdev, R_AX_SYS_STATUS1, B_AX_AUTO_WLPON);
>> +               rtw89_write32_clr(rtwdev, R_AX_GPIO_MUXCFG, B_AX_BOOT_MODE);
>> +               rtw89_write32_clr(rtwdev, R_AX_RSV_CTRL, B_AX_R_DIS_PRST);
>> +       }
>> +
>>         if (on) {
>>                 cfg_seq = chip->pwr_on_seq;
>>                 cfg_func = chip->ops->pwr_on_func;
> 


^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH rtw-next v1 11/13] wifi: rtw89: Add usb.{c,h}
  2025-05-13  6:12   ` Ping-Ke Shih
@ 2025-05-25 22:03     ` Bitterblue Smith
  2025-05-26  3:18       ` Ping-Ke Shih
  0 siblings, 1 reply; 47+ messages in thread
From: Bitterblue Smith @ 2025-05-25 22:03 UTC (permalink / raw)
  To: Ping-Ke Shih, linux-wireless@vger.kernel.org

On 13/05/2025 09:12, Ping-Ke Shih wrote:
> Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
>> Add very basic USB support. No TX/RX aggregation, no TX queues, no
>> switching to USB 3 mode.
>>
>> RTL8851BU and RTL8832BU work.
>>
>> Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
>> ---
>>  drivers/net/wireless/realtek/rtw89/usb.c | 1030 ++++++++++++++++++++++
>>  drivers/net/wireless/realtek/rtw89/usb.h |   61 ++
>>  2 files changed, 1091 insertions(+)
>>  create mode 100644 drivers/net/wireless/realtek/rtw89/usb.c
>>  create mode 100644 drivers/net/wireless/realtek/rtw89/usb.h
>>
>> diff --git a/drivers/net/wireless/realtek/rtw89/usb.c b/drivers/net/wireless/realtek/rtw89/usb.c
>> new file mode 100644
>> index 000000000000..6e8a544b352c
>> --- /dev/null
>> +++ b/drivers/net/wireless/realtek/rtw89/usb.c
>> @@ -0,0 +1,1030 @@
>> +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
>> +/* Copyright(c) 2025  Realtek Corporation
>> + */
>> +
>> +#include <linux/usb.h>
>> +#include "debug.h"
>> +#include "mac.h"
>> +#include "reg.h"
>> +#include "txrx.h"
>> +#include "usb.h"
>> +
>> +static void rtw89_usb_vendorreq(struct rtw89_dev *rtwdev, u32 addr,
>> +                               void *data, u16 len, u8 reqtype)
>> +{
>> +       struct rtw89_usb *rtwusb = rtw89_get_usb_priv(rtwdev);
>> +       struct usb_device *udev = rtwusb->udev;
>> +       unsigned int pipe;
>> +       u16 value, index;
>> +       int attempt, ret;
>> +
>> +       value = addr & 0x0000ffff;
>> +       index = (addr & 0x00ff0000) >> 16;
> 
> u16_get_bits(addr, GENMASK(23, 16)) ?
> 
> 
>> +
>> +       mutex_lock(&rtwusb->vendor_req_mutex);
> 
> rtw89 takes wiphy_lock for control path. Is there any case more than 
> one threads run at the same time?
> 

Maybe not. I just copied this from the vendor driver. How can I be
sure only one thread runs?

I added this above the mutex_lock() today:

	if (mutex_is_locked(&rtwusb->vendor_req_mutex))
		pr_err("mutex already locked elsewhere\n");

So far it hasn't printed the message.

>> +
>> +       for (attempt = 0; attempt < 10; attempt++) {
>> +               *rtwusb->vendor_req_buf = 0;
>> +
>> +               if (reqtype == RTW89_USB_VENQT_READ) {
>> +                       pipe = usb_rcvctrlpipe(udev, 0);
>> +               } else { /* RTW89_USB_VENQT_WRITE */
>> +                       pipe = usb_sndctrlpipe(udev, 0);
>> +
>> +                       memcpy(rtwusb->vendor_req_buf, data, len);
> 
> By "rtwusb->vendor_req_buf = kmalloc(sizeof(u32), GFP_KERNEL);", it seems like 
> buffer size of vendor_req_buf is only 4 bytes. Is it enough space to do
> memcpy()? Also, why not just a local variable ?
> 

It is enough space, len can only be 1, 2, or 4 here. It's not a local
variable because usb_control_msg() needs memory suitable for DMA.

> 
>> +               }
>> +
>> +               ret = usb_control_msg(udev, pipe, RTW89_USB_VENQT, reqtype,
>> +                                     value, index, rtwusb->vendor_req_buf,
>> +                                     len, 500);
>> +
>> +               if (ret == len) { /* Success */
>> +                       atomic_set(&rtwusb->continual_io_error, 0);
>> +
>> +                       if (reqtype == RTW89_USB_VENQT_READ)
>> +                               memcpy(data, rtwusb->vendor_req_buf, len);
>> +
>> +                       break;
>> +               }
>> +
>> +               if (ret == -ESHUTDOWN || ret == -ENODEV)
>> +                       set_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags);
>> +               else if (ret < 0)
>> +                       rtw89_warn(rtwdev,
>> +                                  "usb %s%u 0x%x fail ret=%d value=0x%x attempt=%d\n",
>> +                                  reqtype == RTW89_USB_VENQT_READ ? "read" : "write",
>> +                                  len * 8, addr, ret,
>> +                                  le32_to_cpup(rtwusb->vendor_req_buf),
>> +                                  attempt);
>> +               else if (ret > 0 && reqtype == RTW89_USB_VENQT_READ)
>> +                       memcpy(data, rtwusb->vendor_req_buf, len);
>> +
>> +               if (atomic_inc_return(&rtwusb->continual_io_error) > 4) {
>> +                       set_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags);
>> +                       break;
>> +               }
>> +       }
>> +
>> +       mutex_unlock(&rtwusb->vendor_req_mutex);
>> +}
>> +
>> +static u32 rtw89_usb_read_cmac(struct rtw89_dev *rtwdev, u32 addr)
>> +{
>> +       u32 addr32, val32, shift;
>> +       __le32 data = 0;
>> +       int count;
>> +
>> +       addr32 = addr & ~0x3;
>> +       shift = (addr & 0x3) * 8;
>> +
>> +       for (count = 0; ; count++) {
>> +               rtw89_usb_vendorreq(rtwdev, addr32, &data, 4,
>> +                                   RTW89_USB_VENQT_READ);
>> +
>> +               val32 = le32_to_cpu(data);
>> +
> 
> no empty line between assignment and immediate checking. 
> 
>> +               if (val32 != RTW89_R32_DEAD)
>> +                       break;
>> +
>> +               if (count >= MAC_REG_POOL_COUNT) {
>> +                       rtw89_warn(rtwdev, "%s: addr %#x = %#x\n",
>> +                                  __func__, addr32, val32);
>> +                       val32 = RTW89_R32_DEAD;
>> +                       break;
>> +               }
>> +
>> +               rtw89_write32(rtwdev, R_AX_CK_EN, B_AX_CMAC_ALLCKEN);
>> +       }
>> +
>> +       return val32 >> shift;
>> +}
> 
> [...]
> 
>> +static void rtw89_usb_write_port_complete(struct urb *urb)
>> +{
>> +       struct rtw89_usb_tx_ctrl_block *txcb = urb->context;
>> +       struct rtw89_dev *rtwdev = txcb->rtwdev;
>> +       struct ieee80211_tx_info *info;
>> +       struct sk_buff *skb;
>> +
>> +       while (true) {
> 
> Is it possible that more than one skb are in txcb->tx_ack_queue?
> With USB aggregation afterword, it will become possible?
> 

Right now there is only one skb in txcb->tx_ack_queue. But yes,
with USB TX aggregation it will have several skb. The maximum
number depends on the chip. I think RTL8851BU can take up to 9 in
one USB transfer.

>> +               skb = skb_dequeue(&txcb->tx_ack_queue);
>> +               if (!skb)
>> +                       break;
>> +
>> +               info = IEEE80211_SKB_CB(skb);
>> +               ieee80211_tx_info_clear_status(info);
>> +
>> +               if (urb->status == 0) {
>> +                       if (info->flags & IEEE80211_TX_CTL_NO_ACK)
>> +                               info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED;
>> +                       else
>> +                               info->flags |= IEEE80211_TX_STAT_ACK;
>> +               }
>> +
>> +               ieee80211_tx_status_irqsafe(rtwdev->hw, skb);
>> +       }
>> +
>> +       switch (urb->status) {
>> +       case 0:
>> +       case -EPIPE:
>> +       case -EPROTO:
>> +       case -EINPROGRESS:
>> +       case -ENOENT:
>> +       case -ECONNRESET:
>> +               break;
>> +       default:
>> +               set_bit(RTW89_FLAG_UNPLUGGED, rtwdev->flags);
>> +               break;
>> +       }
>> +
>> +       kfree(txcb);
>> +       usb_free_urb(urb);
>> +}
>> +
> 
> [...]
> 
>> +
>> +static void rtw89_usb_read_port_complete(struct urb *urb);
> 
> Move to beginning of this file. 
> 
>> +
>> +static void rtw89_usb_rx_resubmit(struct rtw89_usb *rtwusb,
>> +                                 struct rtw89_usb_rx_ctrl_block *rxcb,
>> +                                 gfp_t gfp)
>> +{
>> +       struct rtw89_dev *rtwdev = rtwusb->rtwdev;
>> +       struct sk_buff *rx_skb;
>> +       int error;
> 
> Why not 'int ret' in commom? 
> 
> [...]
> 
>> +
>> +static void rtw89_usb_cancel_rx_bufs(struct rtw89_usb *rtwusb)
>> +{
>> +       struct rtw89_usb_rx_ctrl_block *rxcb;
>> +       int i;
>> +
>> +       for (i = 0; i < RTW89_USB_RXCB_NUM; i++) {
>> +               rxcb = &rtwusb->rx_cb[i];
>> +               usb_kill_urb(rxcb->rx_urb);
> 
> rtw89_usb_disconnect() calls rtw89_usb_cancel_rx_bufs() and then call
> rtw89_usb_free_rx_bufs(). Is it a problem that usb_kill_urb() is called twice?
> 

I think it's not a problem because nothing bad happened so far.
But usb_kill_urb() in rtw89_usb_free_rx_bufs() is unnecessary so
I'll remove it.

>> +       }
>> +}
>> +
>> +static void rtw89_usb_free_rx_bufs(struct rtw89_usb *rtwusb)
>> +{
>> +       struct rtw89_usb_rx_ctrl_block *rxcb;
>> +       int i;
>> +
>> +       for (i = 0; i < RTW89_USB_RXCB_NUM; i++) {
>> +               rxcb = &rtwusb->rx_cb[i];
>> +
>> +               usb_kill_urb(rxcb->rx_urb);
>> +               usb_free_urb(rxcb->rx_urb);
>> +       }
>> +}
>> +
> 
> [...]
> 
>> +
>> +static int rtw89_usb_ops_mac_lv1_rcvy(struct rtw89_dev *rtwdev,
>> +                                     enum rtw89_lv1_rcvy_step step)
>> +{
>> +       u32 reg, mask;
>> +
>> +       switch (rtwdev->chip->chip_id) {
>> +       case RTL8851B:
>> +       case RTL8852A:
>> +       case RTL8852B:
>> +               reg = R_AX_USB_WLAN0_1;
>> +               mask = B_AX_USBRX_RST | B_AX_USBTX_RST;
>> +               break;
>> +       case RTL8852C:
>> +               reg = R_AX_USB_WLAN0_1_V1;
>> +               mask = B_AX_USBRX_RST_V1 | B_AX_USBTX_RST_V1;
>> +               break;
>> +       default:
>> +               rtw89_err(rtwdev, "%s: fix me\n", __func__);
>> +               return -EOPNOTSUPP;
>> +       }
>> +
>> +       switch (step) {
>> +       case RTW89_LV1_RCVY_STEP_1:
>> +               rtw89_write32_set(rtwdev, reg, mask);
>> +
>> +               msleep(30);
>> +
> 
> maybe no need this empty line.
> 
>> +               break;
>> +       case RTW89_LV1_RCVY_STEP_2:
>> +               rtw89_write32_clr(rtwdev, reg, mask);
>> +
> 
> no need this empty line.
> 
>> +               break;
>> +       default:
>> +               return -EINVAL;
>> +       }
>> +
>> +       return 0;
>> +}
>> +
> 
> [...]
> 
>> +static int rtw89_usb_intf_init(struct rtw89_dev *rtwdev,
>> +                              struct usb_interface *intf)
>> +{
>> +       struct rtw89_usb *rtwusb = rtw89_get_usb_priv(rtwdev);
>> +       int ret;
>> +
>> +       ret = rtw89_usb_parse(rtwdev, intf);
>> +       if (ret)
>> +               return ret;
>> +
>> +       rtwusb->vendor_req_buf = kmalloc(sizeof(u32), GFP_KERNEL);
> 
> I mentioned this allocation before. 
> 
>> +       if (!rtwusb->vendor_req_buf)
>> +               return -ENOMEM;
>> +
>> +       rtwusb->udev = usb_get_dev(interface_to_usbdev(intf));
>> +
>> +       usb_set_intfdata(intf, rtwdev->hw);
>> +
>> +       SET_IEEE80211_DEV(rtwdev->hw, &intf->dev);
>> +
>> +       mutex_init(&rtwusb->vendor_req_mutex);
>> +
>> +       return 0;
>> +}
>> +
> 
> [...]
> 
>> diff --git a/drivers/net/wireless/realtek/rtw89/usb.h b/drivers/net/wireless/realtek/rtw89/usb.h
>> new file mode 100644
>> index 000000000000..86caae1b9d0b
>> --- /dev/null
>> +++ b/drivers/net/wireless/realtek/rtw89/usb.h
>> @@ -0,0 +1,61 @@
>> +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
>> +/* Copyright(c) 2025  Realtek Corporation
>> + */
>> +
>> +#ifndef __RTW89_USB_H__
>> +#define __RTW89_USB_H__
>> +
> 
> [...]
> 
>> +
>> +static inline struct rtw89_usb *rtw89_get_usb_priv(struct rtw89_dev *rtwdev)
> 
> Not sure if it is worth of this wrapper. Or just rtw89_usb_priv()? 
> 

I like it because it's shorter than (struct rtw89_usb *)rtwdev->priv.

>> +{
>> +       return (struct rtw89_usb *)rtwdev->priv;
>> +}
>> +
>> +int rtw89_usb_probe(struct usb_interface *intf,
>> +                   const struct usb_device_id *id);
>> +void rtw89_usb_disconnect(struct usb_interface *intf);
>> +
>> +#endif
>> --
>> 2.49.0
> 


^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH rtw-next v1 00/13] wifi: rtw89: Add support for USB devices
  2025-05-13  7:07 ` Ping-Ke Shih
@ 2025-05-25 22:03   ` Bitterblue Smith
  2025-05-26  1:35     ` Ping-Ke Shih
  0 siblings, 1 reply; 47+ messages in thread
From: Bitterblue Smith @ 2025-05-25 22:03 UTC (permalink / raw)
  To: Ping-Ke Shih, linux-wireless@vger.kernel.org

On 13/05/2025 10:07, Ping-Ke Shih wrote:
> Ping-Ke Shih wrote:
>> Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
>>>
>>> Add support for USB devices, starting with just RTL8851BU.
>>
>> Thanks for your work!!
> 
> Have you also tested AP mode? If not, please add a patch to disable it
> temporarily as a transition solution, like rtw88. 
> 

I tested it only for a few minutes with RTL8851BU and RTL8832BU.
My phone can connect to both.

>>
>>> RTL8832BU/RTL8852BU can be supported easily later. RTL8832CU/RTL8852CU
>>> can be supported as well, but it keeps losing the connection.
>>>
>>> This is based on rtw88_usb and the official rtl8851bu driver
>>> v1.19.10-70-g84e35c28d.20231019 from here:
>>> https://github.com/fofajardo/rtl8851bu
>>>
>>> I didn't test with any PCI devices.
>>
>> I tested RTL8851BE. It works as usual.
> 


^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH rtw-next v1 02/13] wifi: rtw89: Get dle_mem via rtw89_hci_dle_mem()
  2025-05-14  0:56   ` Ping-Ke Shih
@ 2025-05-25 22:04     ` Bitterblue Smith
  2025-05-26  2:52       ` Ping-Ke Shih
  0 siblings, 1 reply; 47+ messages in thread
From: Bitterblue Smith @ 2025-05-25 22:04 UTC (permalink / raw)
  To: Ping-Ke Shih, linux-wireless@vger.kernel.org

On 14/05/2025 03:56, Ping-Ke Shih wrote:
> Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
>> Don't access dle_mem in get_dle_mem_cfg() directly. USB 2, USB 3, and
>> SDIO will need different sets of values.
>>
>> Rename dle_mem in struct rtw89_chip_info to dle_mem_pcie and get it
>> via rtw89_hci_dle_mem() and rtw89_pci_ops_dle_mem().
>>
>> Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
>> ---
>>  drivers/net/wireless/realtek/rtw89/core.h      | 10 +++++++++-
>>  drivers/net/wireless/realtek/rtw89/mac.c       |  2 +-
>>  drivers/net/wireless/realtek/rtw89/pci.c       |  8 ++++++++
>>  drivers/net/wireless/realtek/rtw89/rtw8851b.c  |  2 +-
>>  drivers/net/wireless/realtek/rtw89/rtw8852a.c  |  2 +-
>>  drivers/net/wireless/realtek/rtw89/rtw8852b.c  |  2 +-
>>  drivers/net/wireless/realtek/rtw89/rtw8852bt.c |  2 +-
>>  drivers/net/wireless/realtek/rtw89/rtw8852c.c  |  2 +-
>>  drivers/net/wireless/realtek/rtw89/rtw8922a.c  |  2 +-
>>  9 files changed, 24 insertions(+), 8 deletions(-)
>>
>> diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
>> index be1259cfa712..afcf0353a625 100644
>> --- a/drivers/net/wireless/realtek/rtw89/core.h
>> +++ b/drivers/net/wireless/realtek/rtw89/core.h
>> @@ -3579,6 +3579,8 @@ struct rtw89_hci_ops {
>>         void (*disable_intr)(struct rtw89_dev *rtwdev);
>>         void (*enable_intr)(struct rtw89_dev *rtwdev);
>>         int (*rst_bdram)(struct rtw89_dev *rtwdev);
> 
> an empty line
> 
>> +       const struct rtw89_dle_mem *(*dle_mem)(struct rtw89_dev *rtwdev,
>> +                                              u8 qta_mode);
>>  };
>>
>>  struct rtw89_hci_info {
>> @@ -4271,7 +4273,7 @@ struct rtw89_chip_info {
>>         bool dis_2g_40m_ul_ofdma;
>>         u32 rsvd_ple_ofst;
>>         const struct rtw89_hfc_param_ini *hfc_param_ini;
>> -       const struct rtw89_dle_mem *dle_mem;
>> +       const struct rtw89_dle_mem *dle_mem_pcie;
> 
> I reconsider if this can be an array with a new enum = {PCIE, USB2, USB3, SDIO}
> stored in hal->hci_dle_mem_type. Then, consumers can just access it via
> chip->dle_mem[hal->hci_dle_mem_type][quota]. But, I'm not sure if USB
> subsystem can notify driver when USB speed is changed. 
> 
> This is a thought to simply the struct definition. 
> 

The hard part is naming the new enum. It's basically rtw89_hci_type
but more detailed.

I don't expect the USB speed to change during the lifetime of struct
rtw89_dev. When the device switches from USB 2 to USB 3 it disconnects
and reappears as a new device:

Apr 21 22:02:22 ideapad2 kernel: usb 1-4: new high-speed USB device number 17 using xhci_hcd
Apr 21 22:02:22 ideapad2 kernel: usb 1-4: New USB device found, idVendor=0bda, idProduct=c832, bcdDevice= 0.00
Apr 21 22:02:22 ideapad2 kernel: usb 1-4: New USB device strings: Mfr=1, Product=2, SerialNumber=3
Apr 21 22:02:22 ideapad2 kernel: usb 1-4: Product: 802.11ax WLAN Adapter
Apr 21 22:02:22 ideapad2 kernel: usb 1-4: Manufacturer: Realtek
Apr 21 22:02:22 ideapad2 kernel: usb 1-4: SerialNumber: 00e04c000001
Apr 21 22:02:24 ideapad2 kernel: eric-tx CALL alloc_txring !!!!
Apr 21 22:02:24 ideapad2 kernel: usb 1-4: USB disconnect, device number 17
Apr 21 22:02:24 ideapad2 kernel: rtl8852cu 1-4:1.0: Runtime PM usage count underflow!

Apr 21 22:02:27 ideapad2 kernel: usb 2-4: new SuperSpeed USB device number 2 using xhci_hcd
Apr 21 22:02:27 ideapad2 kernel: usb 2-4: New USB device found, idVendor=0bda, idProduct=c832, bcdDevice= 0.00
Apr 21 22:02:28 ideapad2 kernel: usb 2-4: New USB device strings: Mfr=1, Product=2, SerialNumber=3
Apr 21 22:02:28 ideapad2 kernel: usb 2-4: Product: 802.11ax WLAN Adapter
Apr 21 22:02:28 ideapad2 kernel: usb 2-4: Manufacturer: Realtek
Apr 21 22:02:28 ideapad2 kernel: usb 2-4: SerialNumber: 00e04c000001
Apr 21 22:02:28 ideapad2 kernel: eric-tx CALL alloc_txring !!!!
Apr 21 22:02:28 ideapad2 kernel: rtl8852cu 2-4:1.0 wlp3s0f3u4: renamed from wlan0

>>         u8 wde_qempty_acq_grpnum;
>>         u8 wde_qempty_mgq_grpsel;
>>         u32 rf_base_addr[2];
>> @@ -6146,6 +6148,12 @@ static inline void rtw89_hci_clear(struct rtw89_dev *rtwdev, struct pci_dev *pde
>>                 rtwdev->hci.ops->clear(rtwdev, pdev);
>>  }
>>
>> +static inline const
>> +struct rtw89_dle_mem *rtw89_hci_dle_mem(struct rtw89_dev *rtwdev, u8 qta_mode)
>> +{
>> +       return rtwdev->hci.ops->dle_mem(rtwdev, qta_mode);
>> +}
>> +
>>  static inline
>>  struct rtw89_tx_skb_data *RTW89_TX_SKB_CB(struct sk_buff *skb)
>>  {
>> diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
>> index 592fbb6d2728..77d35db3e133 100644
>> --- a/drivers/net/wireless/realtek/rtw89/mac.c
>> +++ b/drivers/net/wireless/realtek/rtw89/mac.c
>> @@ -1719,7 +1719,7 @@ static const struct rtw89_dle_mem *get_dle_mem_cfg(struct rtw89_dev *rtwdev,
>>         struct rtw89_mac_info *mac = &rtwdev->mac;
>>         const struct rtw89_dle_mem *cfg;
>>
>> -       cfg = &rtwdev->chip->dle_mem[mode];
>> +       cfg = rtw89_hci_dle_mem(rtwdev, mode);
>>         if (!cfg)
>>                 return NULL;
>>
>> diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c
>> index c2fe5a898dc7..1dec603012ba 100644
>> --- a/drivers/net/wireless/realtek/rtw89/pci.c
>> +++ b/drivers/net/wireless/realtek/rtw89/pci.c
>> @@ -4341,6 +4341,13 @@ static int __maybe_unused rtw89_pci_resume(struct device *dev)
>>  SIMPLE_DEV_PM_OPS(rtw89_pm_ops, rtw89_pci_suspend, rtw89_pci_resume);
>>  EXPORT_SYMBOL(rtw89_pm_ops);
>>
>> +static const
>> +struct rtw89_dle_mem *rtw89_pci_ops_dle_mem(struct rtw89_dev *rtwdev,
>> +                                           u8 qta_mode)
>> +{
>> +       return &rtwdev->chip->dle_mem_pcie[qta_mode];
>> +}
>> +
>>  const struct rtw89_pci_gen_def rtw89_pci_gen_ax = {
>>         .isr_rdu = B_AX_RDU_INT,
>>         .isr_halt_c2h = B_AX_HALT_C2H_INT_EN,
>> @@ -4413,6 +4420,7 @@ static const struct rtw89_hci_ops rtw89_pci_ops = {
>>         .disable_intr   = rtw89_pci_disable_intr_lock,
>>         .enable_intr    = rtw89_pci_enable_intr_lock,
>>         .rst_bdram      = rtw89_pci_reset_bdram,
> 
> an empty line
> 
>> +       .dle_mem        = rtw89_pci_ops_dle_mem,
>>  };
>>
> 
> [...]
> 
> 


^ permalink raw reply	[flat|nested] 47+ messages in thread

* RE: [PATCH rtw-next v1 00/13] wifi: rtw89: Add support for USB devices
  2025-05-25 22:03   ` Bitterblue Smith
@ 2025-05-26  1:35     ` Ping-Ke Shih
  0 siblings, 0 replies; 47+ messages in thread
From: Ping-Ke Shih @ 2025-05-26  1:35 UTC (permalink / raw)
  To: Bitterblue Smith, linux-wireless@vger.kernel.org

Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
> On 13/05/2025 10:07, Ping-Ke Shih wrote:
> > Ping-Ke Shih wrote:
> >> Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
> >>>
> >>> Add support for USB devices, starting with just RTL8851BU.
> >>
> >> Thanks for your work!!
> >
> > Have you also tested AP mode? If not, please add a patch to disable it
> > temporarily as a transition solution, like rtw88.
> >
> 
> I tested it only for a few minutes with RTL8851BU and RTL8832BU.
> My phone can connect to both.

Thanks. Please point out this in the last patch you enable USB support,
so that sometime we can recall the supported modes from commit log.



^ permalink raw reply	[flat|nested] 47+ messages in thread

* RE: [PATCH rtw-next v1 05/13] wifi: rtw89: Add hfc_param_ini_usb
  2025-05-25 21:55     ` Bitterblue Smith
@ 2025-05-26  1:51       ` Ping-Ke Shih
  2025-05-26  6:29         ` Ping-Ke Shih
  2025-05-31 20:54         ` Bitterblue Smith
  0 siblings, 2 replies; 47+ messages in thread
From: Ping-Ke Shih @ 2025-05-26  1:51 UTC (permalink / raw)
  To: Bitterblue Smith, linux-wireless@vger.kernel.org

Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
> On 13/05/2025 06:12, Ping-Ke Shih wrote:
> > Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
> >> Add hfc_param_ini_usb to struct rtw89_chip_info. For now initialise it
> >> only for RTL8851B.
> >>
> >> Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
> >> ---
> >
> > [...]
> >
> >
> >> +
> >> +static const struct rtw89_hfc_param_ini rtw8851b_hfc_param_ini_usb[] = {
> >> +       [RTW89_QTA_SCC] = {rtw8851b_hfc_chcfg_usb, &rtw8851b_hfc_pubcfg_usb,
> >> +                          &rtw8851b_hfc_preccfg_usb, RTW89_HCIFC_STF},
> >
> > [RTW89_QTA_WOW] is missing. I'm not sure if current can handle this correctly.
> > Could you try to do WoWLAN with USB? At least, it shouldn't crash.
> >
> 
> RTW89_QTA_WOW is missing because I didn't find an equivalent in
> enum mac_ax_qta_mode in the vendor driver.

Yes, vendor driver doesn't have that. As I know, it does some modifications
from original normal operation quota, such as RTW89_QTA_SCC, because we want
constant definition in upstream driver. I will check internally and get back
to you how it should be for USB devices. 

> 
> I enabled WOWLAN with this command:
> 
> iw phy0 wowlan enable disconnect
> 
> Then I put the computer to sleep (suspend to RAM). There was no crash,
> just some error messages. The computer went to sleep and woke up without
> any other problems. Of course it didn't stay connected to the access
> point during sleep.
> 
> May 23 20:19:46 ideapad2 kernel: rtw89_8851bu 1-2:1.2: qta mode unmatch!
> May 23 20:19:47 ideapad2 kernel: rtw89_8851bu 1-2:1.2: [ERR]get_dle_mem_cfg
> May 23 20:19:47 ideapad2 kernel: rtw89_8851bu 1-2:1.2: [ERR]patch rx qta -22
> May 23 20:19:47 ideapad2 kernel: rtw89_8851bu 1-2:1.2: failed to config mac
> May 23 20:19:47 ideapad2 kernel: rtw89_8851bu 1-2:1.2: wow: failed to enable trx_post
> May 23 20:19:47 ideapad2 kernel: rtw89_8851bu 1-2:1.2: failed to enable wow
> May 23 20:19:47 ideapad2 kernel: rtw89_8851bu 1-2:1.2: failed to suspend for wow -22
> 
> That was without RTW89_QTA_WOW.
> 
> Then I tried to copy RTW89_QTA_SCC in rtw8851b_hfc_param_ini_usb and
> rtw8851b_dle_mem_usb2. With that I think it was able to upload the WOW
> firmware and it stayed connected to the access point, but something
> didn't let the computer go to sleep. It sat there for several minutes
> with a black screen, the power LED on, and connected to the access
> point (but without an IP address), until I clicked the "Disconnect"
> button in the access point's web interface to disconnect this station.
> That's when the computer finally went to sleep.
> 
> So WOWLAN with RTL8851BU needs more work.

Thanks for the test. I'd ask internal experts if USB devices can support
WoW already. But, I guess the answer is yes. Have you tested WoW with
vendor driver? 



^ permalink raw reply	[flat|nested] 47+ messages in thread

* RE: [PATCH rtw-next v1 06/13] wifi: rtw89: Disable some power saving for USB
  2025-05-25 21:57     ` Bitterblue Smith
@ 2025-05-26  2:36       ` Ping-Ke Shih
  0 siblings, 0 replies; 47+ messages in thread
From: Ping-Ke Shih @ 2025-05-26  2:36 UTC (permalink / raw)
  To: Bitterblue Smith, linux-wireless@vger.kernel.org

Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
> On 13/05/2025 06:27, Ping-Ke Shih wrote:
> > Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
> >> Disable rtw89_ps_power_mode_change() and rtw89_mac_send_rpwm() for
> >> USB because they are called in atomic context and accessing hardware
> >> registers results in "scheduling while atomic" errors.
> >
> > I feel rtw89_ps_power_mode_change() should be not in atomic context.
> > Please check this.
> >
> 
> I think you're right, only rtw89_mac_send_rpwm() is called in atomic
> context. rtw89_ps_power_mode_change() is disabled for other reasons:

The rtw89_ps_power_mode_change() is to enter deep power save mode, which
can save more power save but need to leave the mode before you are going
to do IO/TX/RX. That means if you totally disable it, code flow would
be simpler, but power consumption would be higher. Since this is the
first patches to enable USB, I suggest you can disable it totally for
now, and add it later. 

> 
> 1) It calls rtw89_mac_power_mode_change(), which prints errors when
> rtw89_mac_send_rpwm() is disabled.
> 
> 2) With RTL8852CU it calls rtw89_ps_power_mode_change_with_hci()
> which calls napi_schedule(). That results in dereferencing a null
> pointer.

I see. Your implementation doesn't use NAPI for USB devices. 

The rtw89_ps_power_mode_change_with_hci() is to switch IO address for
PCI devices in deep power save mode, and USB devices don't need this.
I think we can run this only if HCI is PCI.



^ permalink raw reply	[flat|nested] 47+ messages in thread

* RE: [PATCH rtw-next v1 09/13] wifi: rtw89: Fix rtw89_mac_power_switch() for USB
  2025-05-25 21:58     ` Bitterblue Smith
@ 2025-05-26  2:45       ` Ping-Ke Shih
  0 siblings, 0 replies; 47+ messages in thread
From: Ping-Ke Shih @ 2025-05-26  2:45 UTC (permalink / raw)
  To: Bitterblue Smith, linux-wireless@vger.kernel.org

Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
> On 13/05/2025 06:50, Ping-Ke Shih wrote:
> > Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
> >> Clear some bits in some registers in order to allow RTL8851BU to power
> >> on. Also tested with RTL8832BU and RTL8832CU.
> >
> > I see mac_pwr_on_pcie_8851b() and mac_pwr_on_usb_8851b() at least in
> > vendor driver. If you use the power on/off functions for USB devices,
> > the problem may disappear.
> >
> 
> I modified rtw8851b_pwr_on_func() and rtw8851b_pwr_off_func() to match
> mac_pwr_on_usb_8851b() and mac_pwr_off_usb_8851b(). It wasn't enough.

The vendor driver does different things for USB and PCI, so please take
them please.

> Without this patch the firmware upload still fails:
> 
> [ 1238.299960] rtw89_8851bu 1-2:1.2: Firmware version 0.29.41.3 (65cefb31), cmd version 0, type 5
> [ 1238.299970] rtw89_8851bu 1-2:1.2: Firmware version 0.29.41.3 (65cefb31), cmd version 0, type 3
> [ 1238.523187] Bluetooth: hci1: RTL: fw version 0x048ad230
> [ 1238.607110] Bluetooth: hci1: AOSP extensions version v1.00
> [ 1238.622986] Bluetooth: MGMT ver 1.23
> [ 1388.109364] rtw89_8851bu 1-2:1.2: [ERR]H2C path ready
> [ 1388.109751] rtw89_8851bu 1-2:1.2: [ERR]fwdl 0x1E0 = 0xc1
> [ 1388.110115] rtw89_8851bu 1-2:1.2: [ERR]fwdl 0x83F0 = 0x120090
> [ 1388.111615] rtw89_8851bu 1-2:1.2: [ERR]fw PC = 0xb890cd07
> [ 1388.111984] rtw89_8851bu 1-2:1.2: [ERR]fw PC = 0xb890cde5
> [ 1388.112358] rtw89_8851bu 1-2:1.2: [ERR]fw PC = 0xb890cd2b
> [ 1388.112740] rtw89_8851bu 1-2:1.2: [ERR]fw PC = 0xb890ef05
> [ 1388.113110] rtw89_8851bu 1-2:1.2: [ERR]fw PC = 0xb890cd2b
> [ 1388.113510] rtw89_8851bu 1-2:1.2: [ERR]fw PC = 0xb890cce3
> [ 1388.113868] rtw89_8851bu 1-2:1.2: [ERR]fw PC = 0xb890cce3
> [ 1388.114234] rtw89_8851bu 1-2:1.2: [ERR]fw PC = 0xb890cded
> [ 1388.114693] rtw89_8851bu 1-2:1.2: [ERR]fw PC = 0xb890cce3
> [ 1388.114986] rtw89_8851bu 1-2:1.2: [ERR]fw PC = 0xb890cce3
> [ 1388.115358] rtw89_8851bu 1-2:1.2: [ERR]fw PC = 0xb890cde9
> [ 1388.115735] rtw89_8851bu 1-2:1.2: [ERR]fw PC = 0xb890cce3
> [ 1388.116109] rtw89_8851bu 1-2:1.2: [ERR]fw PC = 0xb890cce3
> [ 1388.116480] rtw89_8851bu 1-2:1.2: [ERR]fw PC = 0xb89957b3
> [ 1388.116867] rtw89_8851bu 1-2:1.2: [ERR]fw PC = 0xb890cce3
> 
> (By the way, 150 seconds is a long time and this is just the first batch
> of error messages. There are at least two more like the above and each
> takes another 150 seconds to appear. Things freeze:
> 
> [ 1475.693454] INFO: task systemd-journal:284 blocked for more than 122 seconds.
> [ 1475.693750] INFO: task kded6:853 blocked for more than 122 seconds.
> [ 1598.573772] INFO: task upowerd:1021 blocked for more than 122 seconds.
> 
> I haven't figured out how to fix this long delay yet.)
> 
> >>
> >> Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
> >> ---
> >>  drivers/net/wireless/realtek/rtw89/mac.c | 8 ++++++++
> >>  drivers/net/wireless/realtek/rtw89/reg.h | 1 +
> >>  2 files changed, 9 insertions(+)
> >>
> >> diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
> >> index 99f01fff90fe..d3cf67dfabc9 100644
> >> --- a/drivers/net/wireless/realtek/rtw89/mac.c
> >> +++ b/drivers/net/wireless/realtek/rtw89/mac.c
> >> @@ -1458,6 +1458,14 @@ static int rtw89_mac_power_switch(struct rtw89_dev *rtwdev, bool on)
> >>         int ret;
> >>         u8 val;
> >>
> >> +       if (rtwdev->hci.type == RTW89_HCI_TYPE_USB &&
> >> +           rtw89_read32_mask(rtwdev, R_AX_GPIO_MUXCFG, B_AX_BOOT_MODE)) {
> >
> > Not prefer calling a function in if-statement. Suggest to add a function.
> >
> 
> Do you mean add a variable?
> 
>         boot_mode = rtw89_read32_mask(rtwdev, R_AX_GPIO_MUXCFG, B_AX_BOOT_MODE);
> 
>         if (rtwdev->hci.type == RTW89_HCI_TYPE_USB && boot_mode) {

Yes. I prefer this. But I knew originally you would not do the IO before
checking HCI type. So, I suggested to add a function like 
(the naming is not good though)

void rtw89_mac_power_switch_hci(rtwdev, ...)
{
    if (!USB)
        return;

    val = rtw89_read32_mask(rtwdev, R_AX_GPIO_MUXCFG, B_AX_BOOT_MODE));
    if (!val)
        return;

    // do the IO you want. 
}

> 
> 
> >> +               rtw89_write32_clr(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APFN_ONMAC);
> >> +               rtw89_write32_clr(rtwdev, R_AX_SYS_STATUS1, B_AX_AUTO_WLPON);
> >> +               rtw89_write32_clr(rtwdev, R_AX_GPIO_MUXCFG, B_AX_BOOT_MODE);
> >> +               rtw89_write32_clr(rtwdev, R_AX_RSV_CTRL, B_AX_R_DIS_PRST);
> >> +       }
> >> +
> >>         if (on) {
> >>                 cfg_seq = chip->pwr_on_seq;
> >>                 cfg_func = chip->ops->pwr_on_func;
> >


^ permalink raw reply	[flat|nested] 47+ messages in thread

* RE: [PATCH rtw-next v1 02/13] wifi: rtw89: Get dle_mem via rtw89_hci_dle_mem()
  2025-05-25 22:04     ` Bitterblue Smith
@ 2025-05-26  2:52       ` Ping-Ke Shih
  0 siblings, 0 replies; 47+ messages in thread
From: Ping-Ke Shih @ 2025-05-26  2:52 UTC (permalink / raw)
  To: Bitterblue Smith, linux-wireless@vger.kernel.org

Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
> On 14/05/2025 03:56, Ping-Ke Shih wrote:
> > Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
> >> Don't access dle_mem in get_dle_mem_cfg() directly. USB 2, USB 3, and
> >> SDIO will need different sets of values.
> >>
> >> Rename dle_mem in struct rtw89_chip_info to dle_mem_pcie and get it
> >> via rtw89_hci_dle_mem() and rtw89_pci_ops_dle_mem().
> >>
> >> Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
> >> ---
> >>  drivers/net/wireless/realtek/rtw89/core.h      | 10 +++++++++-
> >>  drivers/net/wireless/realtek/rtw89/mac.c       |  2 +-
> >>  drivers/net/wireless/realtek/rtw89/pci.c       |  8 ++++++++
> >>  drivers/net/wireless/realtek/rtw89/rtw8851b.c  |  2 +-
> >>  drivers/net/wireless/realtek/rtw89/rtw8852a.c  |  2 +-
> >>  drivers/net/wireless/realtek/rtw89/rtw8852b.c  |  2 +-
> >>  drivers/net/wireless/realtek/rtw89/rtw8852bt.c |  2 +-
> >>  drivers/net/wireless/realtek/rtw89/rtw8852c.c  |  2 +-
> >>  drivers/net/wireless/realtek/rtw89/rtw8922a.c  |  2 +-
> >>  9 files changed, 24 insertions(+), 8 deletions(-)
> >>
> >> diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
> >> index be1259cfa712..afcf0353a625 100644
> >> --- a/drivers/net/wireless/realtek/rtw89/core.h
> >> +++ b/drivers/net/wireless/realtek/rtw89/core.h
> >> @@ -3579,6 +3579,8 @@ struct rtw89_hci_ops {
> >>         void (*disable_intr)(struct rtw89_dev *rtwdev);
> >>         void (*enable_intr)(struct rtw89_dev *rtwdev);
> >>         int (*rst_bdram)(struct rtw89_dev *rtwdev);
> >
> > an empty line
> >
> >> +       const struct rtw89_dle_mem *(*dle_mem)(struct rtw89_dev *rtwdev,
> >> +                                              u8 qta_mode);
> >>  };
> >>
> >>  struct rtw89_hci_info {
> >> @@ -4271,7 +4273,7 @@ struct rtw89_chip_info {
> >>         bool dis_2g_40m_ul_ofdma;
> >>         u32 rsvd_ple_ofst;
> >>         const struct rtw89_hfc_param_ini *hfc_param_ini;
> >> -       const struct rtw89_dle_mem *dle_mem;
> >> +       const struct rtw89_dle_mem *dle_mem_pcie;
> >
> > I reconsider if this can be an array with a new enum = {PCIE, USB2, USB3, SDIO}
> > stored in hal->hci_dle_mem_type. Then, consumers can just access it via
> > chip->dle_mem[hal->hci_dle_mem_type][quota]. But, I'm not sure if USB
> > subsystem can notify driver when USB speed is changed.
> >
> > This is a thought to simply the struct definition.
> >
> 
> The hard part is naming the new enum. It's basically rtw89_hci_type
> but more detailed.

If it only used by DLE, maybe rtw89_hci_dle_type is fine?

> 
> I don't expect the USB speed to change during the lifetime of struct
> rtw89_dev. When the device switches from USB 2 to USB 3 it disconnects
> and reappears as a new device:

So seemingly it is workable to store the USB speed in a variable at USB probe.
Please try if it looks good.

> 
> Apr 21 22:02:22 ideapad2 kernel: usb 1-4: new high-speed USB device number 17 using xhci_hcd
> Apr 21 22:02:22 ideapad2 kernel: usb 1-4: New USB device found, idVendor=0bda, idProduct=c832, bcdDevice=
> 0.00
> Apr 21 22:02:22 ideapad2 kernel: usb 1-4: New USB device strings: Mfr=1, Product=2, SerialNumber=3
> Apr 21 22:02:22 ideapad2 kernel: usb 1-4: Product: 802.11ax WLAN Adapter
> Apr 21 22:02:22 ideapad2 kernel: usb 1-4: Manufacturer: Realtek
> Apr 21 22:02:22 ideapad2 kernel: usb 1-4: SerialNumber: 00e04c000001
> Apr 21 22:02:24 ideapad2 kernel: eric-tx CALL alloc_txring !!!!
> Apr 21 22:02:24 ideapad2 kernel: usb 1-4: USB disconnect, device number 17
> Apr 21 22:02:24 ideapad2 kernel: rtl8852cu 1-4:1.0: Runtime PM usage count underflow!
> 
> Apr 21 22:02:27 ideapad2 kernel: usb 2-4: new SuperSpeed USB device number 2 using xhci_hcd
> Apr 21 22:02:27 ideapad2 kernel: usb 2-4: New USB device found, idVendor=0bda, idProduct=c832, bcdDevice=
> 0.00
> Apr 21 22:02:28 ideapad2 kernel: usb 2-4: New USB device strings: Mfr=1, Product=2, SerialNumber=3
> Apr 21 22:02:28 ideapad2 kernel: usb 2-4: Product: 802.11ax WLAN Adapter
> Apr 21 22:02:28 ideapad2 kernel: usb 2-4: Manufacturer: Realtek
> Apr 21 22:02:28 ideapad2 kernel: usb 2-4: SerialNumber: 00e04c000001
> Apr 21 22:02:28 ideapad2 kernel: eric-tx CALL alloc_txring !!!!
> Apr 21 22:02:28 ideapad2 kernel: rtl8852cu 2-4:1.0 wlp3s0f3u4: renamed from wlan0
> 


^ permalink raw reply	[flat|nested] 47+ messages in thread

* RE: [PATCH rtw-next v1 11/13] wifi: rtw89: Add usb.{c,h}
  2025-05-25 22:03     ` Bitterblue Smith
@ 2025-05-26  3:18       ` Ping-Ke Shih
  2025-05-31 21:03         ` Bitterblue Smith
  0 siblings, 1 reply; 47+ messages in thread
From: Ping-Ke Shih @ 2025-05-26  3:18 UTC (permalink / raw)
  To: Bitterblue Smith, linux-wireless@vger.kernel.org

Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
> On 13/05/2025 09:12, Ping-Ke Shih wrote:
> > Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
> >> Add very basic USB support. No TX/RX aggregation, no TX queues, no
> >> switching to USB 3 mode.
> >>
> >> RTL8851BU and RTL8832BU work.
> >>
> >> Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
> >> ---
> >>  drivers/net/wireless/realtek/rtw89/usb.c | 1030 ++++++++++++++++++++++
> >>  drivers/net/wireless/realtek/rtw89/usb.h |   61 ++
> >>  2 files changed, 1091 insertions(+)
> >>  create mode 100644 drivers/net/wireless/realtek/rtw89/usb.c
> >>  create mode 100644 drivers/net/wireless/realtek/rtw89/usb.h
> >>
> >> diff --git a/drivers/net/wireless/realtek/rtw89/usb.c b/drivers/net/wireless/realtek/rtw89/usb.c
> >> new file mode 100644
> >> index 000000000000..6e8a544b352c
> >> --- /dev/null
> >> +++ b/drivers/net/wireless/realtek/rtw89/usb.c
> >> @@ -0,0 +1,1030 @@
> >> +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
> >> +/* Copyright(c) 2025  Realtek Corporation
> >> + */
> >> +
> >> +#include <linux/usb.h>
> >> +#include "debug.h"
> >> +#include "mac.h"
> >> +#include "reg.h"
> >> +#include "txrx.h"
> >> +#include "usb.h"
> >> +
> >> +static void rtw89_usb_vendorreq(struct rtw89_dev *rtwdev, u32 addr,
> >> +                               void *data, u16 len, u8 reqtype)
> >> +{
> >> +       struct rtw89_usb *rtwusb = rtw89_get_usb_priv(rtwdev);
> >> +       struct usb_device *udev = rtwusb->udev;
> >> +       unsigned int pipe;
> >> +       u16 value, index;
> >> +       int attempt, ret;
> >> +
> >> +       value = addr & 0x0000ffff;
> >> +       index = (addr & 0x00ff0000) >> 16;
> >
> > u16_get_bits(addr, GENMASK(23, 16)) ?
> >
> >
> >> +
> >> +       mutex_lock(&rtwusb->vendor_req_mutex);
> >
> > rtw89 takes wiphy_lock for control path. Is there any case more than
> > one threads run at the same time?
> >
> 
> Maybe not. I just copied this from the vendor driver. How can I be
> sure only one thread runs?

For rtw89, currently all ieee80211_ops take wiphy_lock except to TX related
ops. The works forked by rtw89 use wiphy works basically. Some works still 
use ieee80211 works only if they only set a simple flags or so. 

Here, I would like to avoid adding unnecessary mutex at development stage,
because it is hard to remove a mutex with simple review. You can see only 
one existing mutex is 'struct mutex rf_mutex'. I want to remove it, but
I'm still afraid that I miss something by review. 

> 
> I added this above the mutex_lock() today:
> 
>         if (mutex_is_locked(&rtwusb->vendor_req_mutex))
>                 pr_err("mutex already locked elsewhere\n");
> 
> So far it hasn't printed the message.

Not sure if this function depends on lock debugging of kernel options.

By the experiments, this mutex seems to be unnecessary, right?



^ permalink raw reply	[flat|nested] 47+ messages in thread

* RE: [PATCH rtw-next v1 05/13] wifi: rtw89: Add hfc_param_ini_usb
  2025-05-26  1:51       ` Ping-Ke Shih
@ 2025-05-26  6:29         ` Ping-Ke Shih
  2025-05-31 20:57           ` Bitterblue Smith
  2025-05-31 20:54         ` Bitterblue Smith
  1 sibling, 1 reply; 47+ messages in thread
From: Ping-Ke Shih @ 2025-05-26  6:29 UTC (permalink / raw)
  To: Bitterblue Smith, linux-wireless@vger.kernel.org

Ping-Ke Shih <pkshih@realtek.com> wrote:
> Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
> > On 13/05/2025 06:12, Ping-Ke Shih wrote:
> > > Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
> > >> Add hfc_param_ini_usb to struct rtw89_chip_info. For now initialise it
> > >> only for RTL8851B.
> > >>
> > >> Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
> > >> ---
> > >
> > > [...]
> > >
> > >
> > >> +
> > >> +static const struct rtw89_hfc_param_ini rtw8851b_hfc_param_ini_usb[] = {
> > >> +       [RTW89_QTA_SCC] = {rtw8851b_hfc_chcfg_usb, &rtw8851b_hfc_pubcfg_usb,
> > >> +                          &rtw8851b_hfc_preccfg_usb, RTW89_HCIFC_STF},
> > >
> > > [RTW89_QTA_WOW] is missing. I'm not sure if current can handle this correctly.
> > > Could you try to do WoWLAN with USB? At least, it shouldn't crash.
> > >
> >
> > RTW89_QTA_WOW is missing because I didn't find an equivalent in
> > enum mac_ax_qta_mode in the vendor driver.
> 
> Yes, vendor driver doesn't have that. As I know, it does some modifications
> from original normal operation quota, such as RTW89_QTA_SCC, because we want
> constant definition in upstream driver. I will check internally and get back
> to you how it should be for USB devices.

The main function to get QTA_WOW is redu_wowlan_rx_qta(). 

Take RTL8851BE as an example, 

Based on RTW89_QTA_SCC:
  cfg->ple_size->pge_size =>rtw89_mac_size.ple_size6
  =>.ple_size6 = {RTW89_PLE_PG_128, 496, 16,},
  rdu_pg_num = PLE_QTA_PG128B_12KB = 96

QTA6:
  .ple_qt18 = {147, 0, 16, 20, 17, 13, 89, 0, 32, 14, 8, 0,}, //min
  .ple_qt58 = {147, 0, 16, 20, 157, 13, 229, 0, 172, 14, 24, 0,}, //max
                                       ^^^^
  qta_min = 89
  qta_max = 229

  new_qta = (qta_max - qta_min) < rdu_pg_num ?
          qta_min : (qta_max - rdu_pg_num);
        = 229 - 96 = 133

QTA7:

  .ple_qt18 = {147, 0, 16, 20, 17, 13, 89, 0, 32, 14, 8, 0,}, //min
  .ple_qt58 = {147, 0, 16, 20, 157, 13, 229, 0, 172, 14, 24, 0,}, //max
                                           ^^^^

  qta_min = 0 
  qta_max = 0

  new_qta = (qta_max - qta_min) < rdu_pg_num ?
          qta_min : (qta_max - rdu_pg_num);
          = 0

Finally:

  .ple_qt_51b_wow = {147, 0, 16, 20, 157, 13, 133, 0, 172, 14, 24, 0,},
                                              ^^^^^^

A way is to induce the quota by eyes. Another way is to add debug message
in vendor driver to show these quota -- this would be much simpler. 



^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH rtw-next v1 05/13] wifi: rtw89: Add hfc_param_ini_usb
  2025-05-26  1:51       ` Ping-Ke Shih
  2025-05-26  6:29         ` Ping-Ke Shih
@ 2025-05-31 20:54         ` Bitterblue Smith
  1 sibling, 0 replies; 47+ messages in thread
From: Bitterblue Smith @ 2025-05-31 20:54 UTC (permalink / raw)
  To: Ping-Ke Shih, linux-wireless@vger.kernel.org

On 26/05/2025 04:51, Ping-Ke Shih wrote:
> Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
>> On 13/05/2025 06:12, Ping-Ke Shih wrote:
>>> Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
>>>> Add hfc_param_ini_usb to struct rtw89_chip_info. For now initialise it
>>>> only for RTL8851B.
>>>>
>>>> Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
>>>> ---
>>>
>>> [...]
>>>
>>>
>>>> +
>>>> +static const struct rtw89_hfc_param_ini rtw8851b_hfc_param_ini_usb[] = {
>>>> +       [RTW89_QTA_SCC] = {rtw8851b_hfc_chcfg_usb, &rtw8851b_hfc_pubcfg_usb,
>>>> +                          &rtw8851b_hfc_preccfg_usb, RTW89_HCIFC_STF},
>>>
>>> [RTW89_QTA_WOW] is missing. I'm not sure if current can handle this correctly.
>>> Could you try to do WoWLAN with USB? At least, it shouldn't crash.
>>>
>>
>> RTW89_QTA_WOW is missing because I didn't find an equivalent in
>> enum mac_ax_qta_mode in the vendor driver.
> 
> Yes, vendor driver doesn't have that. As I know, it does some modifications
> from original normal operation quota, such as RTW89_QTA_SCC, because we want
> constant definition in upstream driver. I will check internally and get back
> to you how it should be for USB devices. 
> 
>>
>> I enabled WOWLAN with this command:
>>
>> iw phy0 wowlan enable disconnect
>>
>> Then I put the computer to sleep (suspend to RAM). There was no crash,
>> just some error messages. The computer went to sleep and woke up without
>> any other problems. Of course it didn't stay connected to the access
>> point during sleep.
>>
>> May 23 20:19:46 ideapad2 kernel: rtw89_8851bu 1-2:1.2: qta mode unmatch!
>> May 23 20:19:47 ideapad2 kernel: rtw89_8851bu 1-2:1.2: [ERR]get_dle_mem_cfg
>> May 23 20:19:47 ideapad2 kernel: rtw89_8851bu 1-2:1.2: [ERR]patch rx qta -22
>> May 23 20:19:47 ideapad2 kernel: rtw89_8851bu 1-2:1.2: failed to config mac
>> May 23 20:19:47 ideapad2 kernel: rtw89_8851bu 1-2:1.2: wow: failed to enable trx_post
>> May 23 20:19:47 ideapad2 kernel: rtw89_8851bu 1-2:1.2: failed to enable wow
>> May 23 20:19:47 ideapad2 kernel: rtw89_8851bu 1-2:1.2: failed to suspend for wow -22
>>
>> That was without RTW89_QTA_WOW.
>>
>> Then I tried to copy RTW89_QTA_SCC in rtw8851b_hfc_param_ini_usb and
>> rtw8851b_dle_mem_usb2. With that I think it was able to upload the WOW
>> firmware and it stayed connected to the access point, but something
>> didn't let the computer go to sleep. It sat there for several minutes
>> with a black screen, the power LED on, and connected to the access
>> point (but without an IP address), until I clicked the "Disconnect"
>> button in the access point's web interface to disconnect this station.
>> That's when the computer finally went to sleep.
>>
>> So WOWLAN with RTL8851BU needs more work.
> 
> Thanks for the test. I'd ask internal experts if USB devices can support
> WoW already. But, I guess the answer is yes. Have you tested WoW with
> vendor driver? 
> 
> 

Yes, it works. I can wake up the computer with a Magic Packet.

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH rtw-next v1 05/13] wifi: rtw89: Add hfc_param_ini_usb
  2025-05-26  6:29         ` Ping-Ke Shih
@ 2025-05-31 20:57           ` Bitterblue Smith
  0 siblings, 0 replies; 47+ messages in thread
From: Bitterblue Smith @ 2025-05-31 20:57 UTC (permalink / raw)
  To: Ping-Ke Shih, linux-wireless@vger.kernel.org

On 26/05/2025 09:29, Ping-Ke Shih wrote:
> Ping-Ke Shih <pkshih@realtek.com> wrote:
>> Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
>>> On 13/05/2025 06:12, Ping-Ke Shih wrote:
>>>> Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
>>>>> Add hfc_param_ini_usb to struct rtw89_chip_info. For now initialise it
>>>>> only for RTL8851B.
>>>>>
>>>>> Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
>>>>> ---
>>>>
>>>> [...]
>>>>
>>>>
>>>>> +
>>>>> +static const struct rtw89_hfc_param_ini rtw8851b_hfc_param_ini_usb[] = {
>>>>> +       [RTW89_QTA_SCC] = {rtw8851b_hfc_chcfg_usb, &rtw8851b_hfc_pubcfg_usb,
>>>>> +                          &rtw8851b_hfc_preccfg_usb, RTW89_HCIFC_STF},
>>>>
>>>> [RTW89_QTA_WOW] is missing. I'm not sure if current can handle this correctly.
>>>> Could you try to do WoWLAN with USB? At least, it shouldn't crash.
>>>>
>>>
>>> RTW89_QTA_WOW is missing because I didn't find an equivalent in
>>> enum mac_ax_qta_mode in the vendor driver.
>>
>> Yes, vendor driver doesn't have that. As I know, it does some modifications
>> from original normal operation quota, such as RTW89_QTA_SCC, because we want
>> constant definition in upstream driver. I will check internally and get back
>> to you how it should be for USB devices.
> 
> The main function to get QTA_WOW is redu_wowlan_rx_qta(). 
> 
> Take RTL8851BE as an example, 
> 
> Based on RTW89_QTA_SCC:
>   cfg->ple_size->pge_size =>rtw89_mac_size.ple_size6
>   =>.ple_size6 = {RTW89_PLE_PG_128, 496, 16,},
>   rdu_pg_num = PLE_QTA_PG128B_12KB = 96
> 
> QTA6:
>   .ple_qt18 = {147, 0, 16, 20, 17, 13, 89, 0, 32, 14, 8, 0,}, //min
>   .ple_qt58 = {147, 0, 16, 20, 157, 13, 229, 0, 172, 14, 24, 0,}, //max
>                                        ^^^^
>   qta_min = 89
>   qta_max = 229
> 
>   new_qta = (qta_max - qta_min) < rdu_pg_num ?
>           qta_min : (qta_max - rdu_pg_num);
>         = 229 - 96 = 133
> 
> QTA7:
> 
>   .ple_qt18 = {147, 0, 16, 20, 17, 13, 89, 0, 32, 14, 8, 0,}, //min
>   .ple_qt58 = {147, 0, 16, 20, 157, 13, 229, 0, 172, 14, 24, 0,}, //max
>                                            ^^^^
> 
>   qta_min = 0 
>   qta_max = 0
> 
>   new_qta = (qta_max - qta_min) < rdu_pg_num ?
>           qta_min : (qta_max - rdu_pg_num);
>           = 0
> 
> Finally:
> 
>   .ple_qt_51b_wow = {147, 0, 16, 20, 157, 13, 133, 0, 172, 14, 24, 0,},
>                                               ^^^^^^
> 
> A way is to induce the quota by eyes. Another way is to add debug message
> in vendor driver to show these quota -- this would be much simpler. 
> 
> 

Thank you for the explanation. I calculated the quotas like you showed
above and got WOWLAN to work with RTL8851BU. Well, it goes to sleep
and I can wake it up with a Magic Packet, but there are still problems:

1) "c2h reg timeout" error from rtw89_wow_suspend() ->
rtw89_wow_enable() -> rtw89_wow_enable_trx_post() ->
rtw89_wow_config_mac() -> rtw89_wow_config_mac_ax() ->
rtw89_mac_cpu_io_rx() -> rtw89_fw_msg_reg().

The vendor driver doesn't have this problem.

2) It takes ~250 seconds for the above "c2h reg timeout" error to appear
because rtw89_fw_read_c2h_reg() doesn't take into account that it takes
~250 µs to send a USB control message. It uses read_poll_timeout_atomic()
with a timeout of 1000000 µs and a delay of 1 µs. Changing the delay to
250 µs makes read_poll_timeout_atomic() finish after just 2 seconds.

3) There is a warning when the computer wakes up:

May 28 23:14:59 ideapad2 kernel: ------------[ cut here ]------------
May 28 23:14:59 ideapad2 kernel: WARNING: CPU: 2 PID: 3124 at net/mac80211/iface.c:680 ieee80211_do_stop+0x936/0x950 [mac80211]
May 28 23:14:59 ideapad2 kernel: Modules linked in: ccm rtw89_8852bu(OE) rtw89_8851bu(OE) rtw89_8852b(OE) rtw89_8851b(OE) rtw89_8852b_common(OE) rtw89_usb(OE) rtw89_core(>
May 28 23:14:59 ideapad2 kernel:  snd_hda_codec mousedev sha512_ssse3 snd_rpl_pci_acp6x snd_acp_pci sha256_ssse3 sha1_ssse3 ee1004 snd_hda_core snd_acp_legacy_common snd_>
May 28 23:14:59 ideapad2 kernel: Unloaded tainted modules: 8851bu(OE):1 [last unloaded: 8851bu(OE)]
May 28 23:14:59 ideapad2 kernel: CPU: 2 UID: 0 PID: 3124 Comm: kworker/u16:31 Tainted: G           OE      6.14.2-arch1-1 #1 51440b8a0cc8bb91764dac94f6c2b53455e5a907
May 28 23:14:59 ideapad2 kernel: Tainted: [O]=OOT_MODULE, [E]=UNSIGNED_MODULE
May 28 23:14:59 ideapad2 kernel: Hardware name: LENOVO 82KR/LNVNB161216, BIOS HBCN18WW 08/27/2021
May 28 23:14:59 ideapad2 kernel: Workqueue: async async_run_entry_fn
May 28 23:14:59 ideapad2 kernel: RIP: 0010:ieee80211_do_stop+0x936/0x950 [mac80211]
May 28 23:14:59 ideapad2 kernel: Code: 34 ea e9 92 f9 ff ff 0f b7 f0 48 c7 c7 60 d0 28 c2 e8 9e 1b 3e e9 0f 0b e9 89 f8 ff ff 4c 89 e7 e8 7f f3 ff ff e9 03 fd ff ff <0f> >
May 28 23:14:59 ideapad2 kernel: RSP: 0018:ffff97e05b28ba80 EFLAGS: 00010202
May 28 23:14:59 ideapad2 kernel: RAX: 0000000000000004 RBX: ffff8cc46a388a80 RCX: 0000000000000000
May 28 23:14:59 ideapad2 kernel: RDX: 0000000000000001 RSI: 0000000000000000 RDI: ffff8cc51c4810ec
May 28 23:14:59 ideapad2 kernel: RBP: ffff97e05b28bb20 R08: ffff8cc5783ad200 R09: 000000008010000d
May 28 23:14:59 ideapad2 kernel: R10: 000000008010000d R11: 0000000000000246 R12: ffff8cc51c480900
May 28 23:14:59 ideapad2 kernel: R13: ffff97e05b28bab0 R14: ffff97e05b28bab0 R15: 0000000000000000
May 28 23:14:59 ideapad2 kernel: FS:  0000000000000000(0000) GS:ffff8cc653500000(0000) knlGS:0000000000000000
May 28 23:14:59 ideapad2 kernel: CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
May 28 23:14:59 ideapad2 kernel: CR2: 0000000000000000 CR3: 0000000140822000 CR4: 00000000003506f0
May 28 23:14:59 ideapad2 kernel: Call Trace:
May 28 23:14:59 ideapad2 kernel:  <TASK>
May 28 23:14:59 ideapad2 kernel:  ? psi_group_change+0x13b/0x310
May 28 23:14:59 ideapad2 kernel:  ieee80211_stop+0x5b/0x1a0 [mac80211 682e229732a6bfe53cb0bbcde81ec2801d27c374]
May 28 23:14:59 ideapad2 kernel:  __dev_close_many+0xaa/0x150
May 28 23:14:59 ideapad2 kernel:  dev_close_many+0xbe/0x1a0
May 28 23:14:59 ideapad2 kernel:  dev_close+0x6f/0xa0
May 28 23:14:59 ideapad2 kernel:  cfg80211_shutdown_all_interfaces+0x4d/0xf0 [cfg80211 fca8a1144424bca742e19d88b98aa1afb064fec0]
May 28 23:14:59 ideapad2 kernel:  ieee80211_remove_interfaces+0x4d/0x230 [mac80211 682e229732a6bfe53cb0bbcde81ec2801d27c374]
May 28 23:14:59 ideapad2 kernel:  ? __pfx_wait_rcu_exp_gp+0x10/0x10
May 28 23:14:59 ideapad2 kernel:  ieee80211_unregister_hw+0x4a/0x130 [mac80211 682e229732a6bfe53cb0bbcde81ec2801d27c374]
May 28 23:14:59 ideapad2 kernel:  rtw89_core_unregister+0x3a/0x50 [rtw89_core 6d9cf325b1126b69ab43ddd6b0b9a561d4ea24f8]
May 28 23:14:59 ideapad2 kernel:  rtw89_usb_disconnect+0x53/0xe0 [rtw89_usb 2cf966e0c4b7fe950d436a899adc081e9902c1d8]
May 28 23:14:59 ideapad2 kernel:  usb_unbind_interface+0x90/0x290
May 28 23:14:59 ideapad2 kernel:  device_release_driver_internal+0x19c/0x200
May 28 23:14:59 ideapad2 kernel:  ? __pfx_usb_dev_resume+0x10/0x10
May 28 23:14:59 ideapad2 kernel:  usb_forced_unbind_intf+0x75/0xb0
May 28 23:14:59 ideapad2 kernel:  ? __pfx_usb_dev_resume+0x10/0x10
May 28 23:14:59 ideapad2 kernel:  unbind_marked_interfaces.isra.0+0x59/0x80
May 28 23:14:59 ideapad2 kernel:  usb_resume+0x5a/0x60
May 28 23:14:59 ideapad2 kernel:  dpm_run_callback+0x48/0x150
May 28 23:14:59 ideapad2 kernel:  device_resume+0x140/0x240
May 28 23:14:59 ideapad2 kernel:  async_resume+0x1d/0x30
May 28 23:14:59 ideapad2 kernel:  async_run_entry_fn+0x31/0x140
May 28 23:14:59 ideapad2 kernel:  process_one_work+0x17b/0x330
May 28 23:14:59 ideapad2 kernel:  worker_thread+0x2ce/0x3f0
May 28 23:14:59 ideapad2 kernel:  ? __pfx_worker_thread+0x10/0x10
May 28 23:14:59 ideapad2 kernel:  kthread+0xec/0x230
May 28 23:14:59 ideapad2 kernel:  ? __pfx_kthread+0x10/0x10
May 28 23:14:59 ideapad2 kernel:  ret_from_fork+0x31/0x50
May 28 23:14:59 ideapad2 kernel:  ? __pfx_kthread+0x10/0x10
May 28 23:14:59 ideapad2 kernel:  ret_from_fork_asm+0x1a/0x30
May 28 23:14:59 ideapad2 kernel:  </TASK>
May 28 23:14:59 ideapad2 kernel: ---[ end trace 0000000000000000 ]---

It's this one in ieee80211_do_stop():

	/*
	 * If the interface goes down while suspended, presumably because
	 * the device was unplugged and that happens before our resume,
	 * then the driver is already unconfigured and the remainder of
	 * this function isn't needed.
	 * XXX: what about WoWLAN? If the device has software state, e.g.
	 *	memory allocated, it might expect teardown commands from
	 *	mac80211 here?
	 */
	if (local->suspended) {
		WARN_ON(local->wowlan);

I would like to leave the WOWLAN fixes for later, to keep this set of
patches small.

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH rtw-next v1 11/13] wifi: rtw89: Add usb.{c,h}
  2025-05-26  3:18       ` Ping-Ke Shih
@ 2025-05-31 21:03         ` Bitterblue Smith
  0 siblings, 0 replies; 47+ messages in thread
From: Bitterblue Smith @ 2025-05-31 21:03 UTC (permalink / raw)
  To: Ping-Ke Shih, linux-wireless@vger.kernel.org

On 26/05/2025 06:18, Ping-Ke Shih wrote:
> Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
>> On 13/05/2025 09:12, Ping-Ke Shih wrote:
>>> Bitterblue Smith <rtl8821cerfe2@gmail.com> wrote:
>>>> Add very basic USB support. No TX/RX aggregation, no TX queues, no
>>>> switching to USB 3 mode.
>>>>
>>>> RTL8851BU and RTL8832BU work.
>>>>
>>>> Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
>>>> ---
>>>>  drivers/net/wireless/realtek/rtw89/usb.c | 1030 ++++++++++++++++++++++
>>>>  drivers/net/wireless/realtek/rtw89/usb.h |   61 ++
>>>>  2 files changed, 1091 insertions(+)
>>>>  create mode 100644 drivers/net/wireless/realtek/rtw89/usb.c
>>>>  create mode 100644 drivers/net/wireless/realtek/rtw89/usb.h
>>>>
>>>> diff --git a/drivers/net/wireless/realtek/rtw89/usb.c b/drivers/net/wireless/realtek/rtw89/usb.c
>>>> new file mode 100644
>>>> index 000000000000..6e8a544b352c
>>>> --- /dev/null
>>>> +++ b/drivers/net/wireless/realtek/rtw89/usb.c
>>>> @@ -0,0 +1,1030 @@
>>>> +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
>>>> +/* Copyright(c) 2025  Realtek Corporation
>>>> + */
>>>> +
>>>> +#include <linux/usb.h>
>>>> +#include "debug.h"
>>>> +#include "mac.h"
>>>> +#include "reg.h"
>>>> +#include "txrx.h"
>>>> +#include "usb.h"
>>>> +
>>>> +static void rtw89_usb_vendorreq(struct rtw89_dev *rtwdev, u32 addr,
>>>> +                               void *data, u16 len, u8 reqtype)
>>>> +{
>>>> +       struct rtw89_usb *rtwusb = rtw89_get_usb_priv(rtwdev);
>>>> +       struct usb_device *udev = rtwusb->udev;
>>>> +       unsigned int pipe;
>>>> +       u16 value, index;
>>>> +       int attempt, ret;
>>>> +
>>>> +       value = addr & 0x0000ffff;
>>>> +       index = (addr & 0x00ff0000) >> 16;
>>>
>>> u16_get_bits(addr, GENMASK(23, 16)) ?
>>>
>>>
>>>> +
>>>> +       mutex_lock(&rtwusb->vendor_req_mutex);
>>>
>>> rtw89 takes wiphy_lock for control path. Is there any case more than
>>> one threads run at the same time?
>>>
>>
>> Maybe not. I just copied this from the vendor driver. How can I be
>> sure only one thread runs?
> 
> For rtw89, currently all ieee80211_ops take wiphy_lock except to TX related
> ops. The works forked by rtw89 use wiphy works basically. Some works still 
> use ieee80211 works only if they only set a simple flags or so. 
> 
> Here, I would like to avoid adding unnecessary mutex at development stage,
> because it is hard to remove a mutex with simple review. You can see only 
> one existing mutex is 'struct mutex rf_mutex'. I want to remove it, but
> I'm still afraid that I miss something by review. 
> 
>>
>> I added this above the mutex_lock() today:
>>
>>         if (mutex_is_locked(&rtwusb->vendor_req_mutex))
>>                 pr_err("mutex already locked elsewhere\n");
>>
>> So far it hasn't printed the message.
> 
> Not sure if this function depends on lock debugging of kernel options.
> 

I checked, mutex_is_locked() works with my Arch Linux kernel.

> By the experiments, this mutex seems to be unnecessary, right?
> 

Yes, it looks unnecessary.

^ permalink raw reply	[flat|nested] 47+ messages in thread

end of thread, other threads:[~2025-05-31 21:03 UTC | newest]

Thread overview: 47+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-05-04 20:47 [PATCH rtw-next v1 00/13] wifi: rtw89: Add support for USB devices Bitterblue Smith
2025-05-04 20:49 ` [PATCH rtw-next v1 01/13] wifi: rtw89: 8851b: Accept USB devices and load their MAC address Bitterblue Smith
2025-05-13  2:46   ` Ping-Ke Shih
2025-05-04 20:49 ` [PATCH rtw-next v1 02/13] wifi: rtw89: Get dle_mem via rtw89_hci_dle_mem() Bitterblue Smith
2025-05-13  2:51   ` Ping-Ke Shih
2025-05-14  0:56   ` Ping-Ke Shih
2025-05-25 22:04     ` Bitterblue Smith
2025-05-26  2:52       ` Ping-Ke Shih
2025-05-04 20:49 ` [PATCH rtw-next v1 03/13] wifi: rtw89: Rename hfc_param_ini to hfc_param_ini_pcie Bitterblue Smith
2025-05-13  3:04   ` Ping-Ke Shih
2025-05-04 20:50 ` [PATCH rtw-next v1 04/13] wifi: rtw89: Add dle_mem_usb2 and dle_mem_usb3 Bitterblue Smith
2025-05-13  3:06   ` Ping-Ke Shih
2025-05-04 20:51 ` [PATCH rtw-next v1 05/13] wifi: rtw89: Add hfc_param_ini_usb Bitterblue Smith
2025-05-13  3:12   ` Ping-Ke Shih
2025-05-25 21:55     ` Bitterblue Smith
2025-05-26  1:51       ` Ping-Ke Shih
2025-05-26  6:29         ` Ping-Ke Shih
2025-05-31 20:57           ` Bitterblue Smith
2025-05-31 20:54         ` Bitterblue Smith
2025-05-04 20:51 ` [PATCH rtw-next v1 06/13] wifi: rtw89: Disable some power saving for USB Bitterblue Smith
2025-05-13  3:27   ` Ping-Ke Shih
2025-05-25 21:57     ` Bitterblue Smith
2025-05-26  2:36       ` Ping-Ke Shih
2025-05-04 20:51 ` [PATCH rtw-next v1 07/13] wifi: rtw89: Add extra TX headroom " Bitterblue Smith
2025-05-13  3:28   ` Ping-Ke Shih
2025-05-04 20:52 ` [PATCH rtw-next v1 08/13] wifi: rtw89: Hide some errors when the device is unplugged Bitterblue Smith
2025-05-13  3:43   ` Ping-Ke Shih
2025-05-25 21:58     ` Bitterblue Smith
2025-05-04 20:52 ` [PATCH rtw-next v1 09/13] wifi: rtw89: Fix rtw89_mac_power_switch() for USB Bitterblue Smith
2025-05-13  3:50   ` Ping-Ke Shih
2025-05-25 21:58     ` Bitterblue Smith
2025-05-26  2:45       ` Ping-Ke Shih
2025-05-04 20:53 ` [PATCH rtw-next v1 10/13] wifi: rtw89: Add some definitions " Bitterblue Smith
2025-05-13  3:52   ` Ping-Ke Shih
2025-05-04 20:54 ` [PATCH rtw-next v1 11/13] wifi: rtw89: Add usb.{c,h} Bitterblue Smith
2025-05-13  6:12   ` Ping-Ke Shih
2025-05-25 22:03     ` Bitterblue Smith
2025-05-26  3:18       ` Ping-Ke Shih
2025-05-31 21:03         ` Bitterblue Smith
2025-05-04 20:54 ` [PATCH rtw-next v1 12/13] wifi: rtw89: Add rtw8851bu.c Bitterblue Smith
2025-05-13  6:14   ` Ping-Ke Shih
2025-05-04 20:55 ` [PATCH rtw-next v1 13/13] wifi: rtw89: Enable the new USB modules Bitterblue Smith
2025-05-13  6:14   ` Ping-Ke Shih
2025-05-13  6:22 ` [PATCH rtw-next v1 00/13] wifi: rtw89: Add support for USB devices Ping-Ke Shih
2025-05-13  7:07 ` Ping-Ke Shih
2025-05-25 22:03   ` Bitterblue Smith
2025-05-26  1:35     ` Ping-Ke Shih

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).