2022-11-22 14:54:21

by Sascha Hauer

[permalink] [raw]
Subject: [PATCH v3 00/11] RTW88: Add support for USB variants

This is the third round of adding support for the USB variants to the
RTW88 driver. There are a few changes to the last version which make it
worth looking at this version.

First of all RTL8723du and RTL8821cu are tested working now. The issue
here was that the txdesc checksum calculation was wrong. I found the
correct calculation in various downstream drivers found on github.

The second big issue was that TX packet aggregation was wrong. When
aggregating packets each packet start has to be aligned to eight bytes.
The necessary alignment was added to the total URB length before
checking if there is another packet to aggregate, so the URB length
included that padding after the last packet, which is wrong. Fixing
this makes the driver work much more reliably.

I added all people to Cc: who showed interest in this driver and I want
to welcome you for testing and reviewing.

Sascha


Sascha Hauer (11):
rtw88: print firmware type in info message
rtw88: Call rtw_fw_beacon_filter_config() with rtwdev->mutex held
rtw88: Drop rf_lock
rtw88: Drop h2c.lock
rtw88: Drop coex mutex
rtw88: iterate over vif/sta list non-atomically
rtw88: Add common USB chip support
rtw88: Add rtw8821cu chipset support
rtw88: Add rtw8822bu chipset support
rtw88: Add rtw8822cu chipset support
rtw88: Add rtw8723du chipset support

drivers/net/wireless/realtek/rtw88/Kconfig | 47 +
drivers/net/wireless/realtek/rtw88/Makefile | 14 +
drivers/net/wireless/realtek/rtw88/coex.c | 3 +-
drivers/net/wireless/realtek/rtw88/debug.c | 15 +
drivers/net/wireless/realtek/rtw88/fw.c | 13 +-
drivers/net/wireless/realtek/rtw88/hci.h | 9 +-
drivers/net/wireless/realtek/rtw88/mac.c | 3 +
drivers/net/wireless/realtek/rtw88/mac80211.c | 2 +-
drivers/net/wireless/realtek/rtw88/main.c | 12 +-
drivers/net/wireless/realtek/rtw88/main.h | 12 +-
drivers/net/wireless/realtek/rtw88/phy.c | 6 +-
drivers/net/wireless/realtek/rtw88/ps.c | 2 +-
drivers/net/wireless/realtek/rtw88/reg.h | 1 +
drivers/net/wireless/realtek/rtw88/rtw8723d.c | 28 +
drivers/net/wireless/realtek/rtw88/rtw8723d.h | 13 +-
.../net/wireless/realtek/rtw88/rtw8723du.c | 36 +
.../net/wireless/realtek/rtw88/rtw8723du.h | 10 +
drivers/net/wireless/realtek/rtw88/rtw8821c.c | 18 +
drivers/net/wireless/realtek/rtw88/rtw8821c.h | 21 +
.../net/wireless/realtek/rtw88/rtw8821cu.c | 50 +
.../net/wireless/realtek/rtw88/rtw8821cu.h | 10 +
drivers/net/wireless/realtek/rtw88/rtw8822b.c | 19 +
.../net/wireless/realtek/rtw88/rtw8822bu.c | 90 ++
.../net/wireless/realtek/rtw88/rtw8822bu.h | 10 +
drivers/net/wireless/realtek/rtw88/rtw8822c.c | 24 +
.../net/wireless/realtek/rtw88/rtw8822cu.c | 44 +
.../net/wireless/realtek/rtw88/rtw8822cu.h | 10 +
drivers/net/wireless/realtek/rtw88/tx.h | 31 +
drivers/net/wireless/realtek/rtw88/usb.c | 918 ++++++++++++++++++
drivers/net/wireless/realtek/rtw88/usb.h | 107 ++
drivers/net/wireless/realtek/rtw88/util.c | 103 ++
drivers/net/wireless/realtek/rtw88/util.h | 12 +-
32 files changed, 1655 insertions(+), 38 deletions(-)
create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8723du.c
create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8723du.h
create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8821cu.c
create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8821cu.h
create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8822bu.c
create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8822bu.h
create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8822cu.c
create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8822cu.h
create mode 100644 drivers/net/wireless/realtek/rtw88/usb.c
create mode 100644 drivers/net/wireless/realtek/rtw88/usb.h

--
2.30.2


2022-11-22 14:54:25

by Sascha Hauer

[permalink] [raw]
Subject: [PATCH v3 09/11] rtw88: Add rtw8822bu chipset support

Add support for the rtw8822bu chipset based on
https://github.com/ulli-kroll/rtw88-usb.git

Signed-off-by: Sascha Hauer <[email protected]>
---

Notes:
Changes since v1:
- Add more Device IDs from https://github.com/morrownr/88x2bu-20210702.git

drivers/net/wireless/realtek/rtw88/Kconfig | 11 +++
drivers/net/wireless/realtek/rtw88/Makefile | 3 +
drivers/net/wireless/realtek/rtw88/rtw8822b.c | 19 ++++
.../net/wireless/realtek/rtw88/rtw8822bu.c | 90 +++++++++++++++++++
.../net/wireless/realtek/rtw88/rtw8822bu.h | 10 +++
5 files changed, 133 insertions(+)
create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8822bu.c
create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8822bu.h

diff --git a/drivers/net/wireless/realtek/rtw88/Kconfig b/drivers/net/wireless/realtek/rtw88/Kconfig
index 2b500dbefbc2d..10f4e7f88b858 100644
--- a/drivers/net/wireless/realtek/rtw88/Kconfig
+++ b/drivers/net/wireless/realtek/rtw88/Kconfig
@@ -42,6 +42,17 @@ config RTW88_8822BE

802.11ac PCIe wireless network adapter

+config RTW88_8822BU
+ tristate "Realtek 8822BU USB wireless network adapter"
+ depends on USB
+ select RTW88_CORE
+ select RTW88_USB
+ select RTW88_8822B
+ help
+ Select this option will enable support for 8822BU chipset
+
+ 802.11ac USB wireless network adapter
+
config RTW88_8822CE
tristate "Realtek 8822CE PCI wireless network adapter"
depends on PCI
diff --git a/drivers/net/wireless/realtek/rtw88/Makefile b/drivers/net/wireless/realtek/rtw88/Makefile
index 3c1f08f12e44e..1d28cc4fff7b2 100644
--- a/drivers/net/wireless/realtek/rtw88/Makefile
+++ b/drivers/net/wireless/realtek/rtw88/Makefile
@@ -26,6 +26,9 @@ rtw88_8822b-objs := rtw8822b.o rtw8822b_table.o
obj-$(CONFIG_RTW88_8822BE) += rtw88_8822be.o
rtw88_8822be-objs := rtw8822be.o

+obj-$(CONFIG_RTW88_8822BU) += rtw88_8822bu.o
+rtw88_8822bu-objs := rtw8822bu.o
+
obj-$(CONFIG_RTW88_8822C) += rtw88_8822c.o
rtw88_8822c-objs := rtw8822c.o rtw8822c_table.o

diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c
index 690e35c98f6e5..74dfb89b2c948 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c
@@ -26,6 +26,12 @@ static void rtw8822be_efuse_parsing(struct rtw_efuse *efuse,
ether_addr_copy(efuse->addr, map->e.mac_addr);
}

+static void rtw8822bu_efuse_parsing(struct rtw_efuse *efuse,
+ struct rtw8822b_efuse *map)
+{
+ ether_addr_copy(efuse->addr, map->u.mac_addr);
+}
+
static int rtw8822b_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
{
struct rtw_efuse *efuse = &rtwdev->efuse;
@@ -56,6 +62,9 @@ static int rtw8822b_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
case RTW_HCI_TYPE_PCIE:
rtw8822be_efuse_parsing(efuse, map);
break;
+ case RTW_HCI_TYPE_USB:
+ rtw8822bu_efuse_parsing(efuse, map);
+ break;
default:
/* unsupported now */
return -ENOTSUPP;
@@ -1588,6 +1597,15 @@ static void rtw8822b_adaptivity(struct rtw_dev *rtwdev)
rtw_phy_set_edcca_th(rtwdev, l2h, h2l);
}

+static void rtw8822b_fill_txdesc_checksum(struct rtw_dev *rtwdev,
+ struct rtw_tx_pkt_info *pkt_info,
+ u8 *txdesc)
+{
+ size_t words = 32 / 2; /* calculate the first 32 bytes (16 words) */
+
+ fill_txdesc_checksum_common(txdesc, words);
+}
+
static const struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8822b[] = {
{0x0086,
RTW_PWR_CUT_ALL_MSK,
@@ -2163,6 +2181,7 @@ static struct rtw_chip_ops rtw8822b_ops = {
.cfg_csi_rate = rtw_bf_cfg_csi_rate,
.adaptivity_init = rtw8822b_adaptivity_init,
.adaptivity = rtw8822b_adaptivity,
+ .fill_txdesc_checksum = rtw8822b_fill_txdesc_checksum,

.coex_set_init = rtw8822b_coex_cfg_init,
.coex_set_ant_switch = rtw8822b_coex_cfg_ant_switch,
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822bu.c b/drivers/net/wireless/realtek/rtw88/rtw8822bu.c
new file mode 100644
index 0000000000000..d1ddb3a32694f
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822bu.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) 2018-2019 Realtek Corporation
+ */
+
+#include <linux/module.h>
+#include <linux/usb.h>
+#include "main.h"
+#include "rtw8822bu.h"
+#include "usb.h"
+
+static const struct usb_device_id rtw_8822bu_id_table[] = {
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xb812, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) },
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xb82c, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) },
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x2102, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* CCNC */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xb822, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Edimax EW-7822ULC */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xc822, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Edimax EW-7822UTC */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xd822, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Edimax */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xe822, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Edimax */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xf822, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Edimax EW-7822UAD */
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xb81a, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Default ID */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x1841, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* ASUS AC1300 USB-AC55 B1 */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x184c, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* ASUS U2 */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x0B05, 0x19aa, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* ASUS - USB-AC58 rev A1 */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x0B05, 0x1870, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* ASUS */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x0B05, 0x1874, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* ASUS */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x331e, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Dlink - DWA-181 */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x331c, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Dlink - DWA-182 - D1 */
+ {USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x331f, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec)}, /* Dlink - DWA-183 D Ver */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x13b1, 0x0043, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Linksys WUSB6400M */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x13b1, 0x0045, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Linksys WUSB3600 v2 */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x012d, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TP-Link Archer T3U v1 */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0138, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TP-Link Archer T3U Plus v1 */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0115, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TP-Link Archer T4U V3 */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x012e, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TP-LINK */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0116, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TP-LINK */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0117, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TP-LINK */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9055, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Netgear A6150 */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x0e66, 0x0025, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Hawking HW12ACU */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x04ca, 0x8602, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* LiteOn */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x20f4, 0x808a, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TRENDnet TEW-808UBM */
+ {},
+};
+MODULE_DEVICE_TABLE(usb, rtw_8822bu_id_table);
+
+static int rtw8822bu_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ return rtw_usb_probe(intf, id);
+}
+
+static struct usb_driver rtw_8822bu_driver = {
+ .name = "rtw_8822bu",
+ .id_table = rtw_8822bu_id_table,
+ .probe = rtw8822bu_probe,
+ .disconnect = rtw_usb_disconnect,
+};
+module_usb_driver(rtw_8822bu_driver);
+
+MODULE_AUTHOR("Realtek Corporation");
+MODULE_DESCRIPTION("Realtek 802.11ac wireless 8822bu driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822bu.h b/drivers/net/wireless/realtek/rtw88/rtw8822bu.h
new file mode 100644
index 0000000000000..8a6deb28d13aa
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822bu.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2018-2019 Realtek Corporation
+ */
+
+#ifndef __RTW_8822BU_H_
+#define __RTW_8822BU_H_
+
+extern struct rtw_chip_info rtw8822b_hw_spec;
+
+#endif
--
2.30.2

2022-11-22 14:54:49

by Sascha Hauer

[permalink] [raw]
Subject: [PATCH v3 07/11] rtw88: Add common USB chip support

Add the common bits and pieces to add USB support to the RTW88 driver.
This is based on https://github.com/ulli-kroll/rtw88-usb.git which
itself is first written by Neo Jou.

Signed-off-by: neo_jou <[email protected]>
Signed-off-by: Hans Ulli Kroll <[email protected]>
Signed-off-by: Sascha Hauer <[email protected]>
---

Notes:
Changes since v2:
- Fix buffer length for aggregated tx packets
- Increase maximum transmit buffer size to 20KiB as found in downstream drivers
- Change register write functions to synchronous accesses instead of just firing
a URB without waiting for its completion
- requeue rx URBs directly in completion handler rather than having a workqueue
for it.

Changes since v1:
- Make checkpatch.pl clean
- Drop WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL flag
- Use 'ret' as variable name for return values
- Sort variable declarations in reverse Xmas tree order
- Change potentially endless loop to a limited loop
- Change locking to be more obviously correct
- drop unnecessary check for !rtwdev
- make sure the refill workqueue is not restarted again after we have
cancelled it

drivers/net/wireless/realtek/rtw88/Kconfig | 3 +
drivers/net/wireless/realtek/rtw88/Makefile | 2 +
drivers/net/wireless/realtek/rtw88/mac.c | 3 +
drivers/net/wireless/realtek/rtw88/main.c | 4 +
drivers/net/wireless/realtek/rtw88/main.h | 4 +
drivers/net/wireless/realtek/rtw88/reg.h | 1 +
drivers/net/wireless/realtek/rtw88/tx.h | 31 +
drivers/net/wireless/realtek/rtw88/usb.c | 918 ++++++++++++++++++++
drivers/net/wireless/realtek/rtw88/usb.h | 107 +++
9 files changed, 1073 insertions(+)
create mode 100644 drivers/net/wireless/realtek/rtw88/usb.c
create mode 100644 drivers/net/wireless/realtek/rtw88/usb.h

diff --git a/drivers/net/wireless/realtek/rtw88/Kconfig b/drivers/net/wireless/realtek/rtw88/Kconfig
index e3d7cb6c12902..1624c5db69bac 100644
--- a/drivers/net/wireless/realtek/rtw88/Kconfig
+++ b/drivers/net/wireless/realtek/rtw88/Kconfig
@@ -16,6 +16,9 @@ config RTW88_CORE
config RTW88_PCI
tristate

+config RTW88_USB
+ tristate
+
config RTW88_8822B
tristate

diff --git a/drivers/net/wireless/realtek/rtw88/Makefile b/drivers/net/wireless/realtek/rtw88/Makefile
index 834c66ec0af9e..9e095f8181483 100644
--- a/drivers/net/wireless/realtek/rtw88/Makefile
+++ b/drivers/net/wireless/realtek/rtw88/Makefile
@@ -45,4 +45,6 @@ obj-$(CONFIG_RTW88_8821CE) += rtw88_8821ce.o
rtw88_8821ce-objs := rtw8821ce.o

obj-$(CONFIG_RTW88_PCI) += rtw88_pci.o
+obj-$(CONFIG_RTW88_USB) += rtw88_usb.o
rtw88_pci-objs := pci.o
+rtw88_usb-objs := usb.o
diff --git a/drivers/net/wireless/realtek/rtw88/mac.c b/drivers/net/wireless/realtek/rtw88/mac.c
index 52076e89d59a3..5882fc0fb885b 100644
--- a/drivers/net/wireless/realtek/rtw88/mac.c
+++ b/drivers/net/wireless/realtek/rtw88/mac.c
@@ -1032,6 +1032,9 @@ static int txdma_queue_mapping(struct rtw_dev *rtwdev)
if (rtw_chip_wcpu_11ac(rtwdev))
rtw_write32(rtwdev, REG_H2CQ_CSR, BIT_H2CQ_FULL);

+ if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_USB)
+ rtw_write8_set(rtwdev, REG_TXDMA_PQ_MAP, BIT_RXDMA_ARBBW_EN);
+
return 0;
}

diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c
index 0a2ce7f50f412..888427cf3bdf9 100644
--- a/drivers/net/wireless/realtek/rtw88/main.c
+++ b/drivers/net/wireless/realtek/rtw88/main.c
@@ -1783,6 +1783,10 @@ static int rtw_chip_parameter_setup(struct rtw_dev *rtwdev)
rtwdev->hci.rpwm_addr = 0x03d9;
rtwdev->hci.cpwm_addr = 0x03da;
break;
+ case RTW_HCI_TYPE_USB:
+ rtwdev->hci.rpwm_addr = 0xfe58;
+ rtwdev->hci.cpwm_addr = 0xfe57;
+ break;
default:
rtw_err(rtwdev, "unsupported hci type\n");
return -EINVAL;
diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h
index 77fd48b6cc453..165f299e8e1f9 100644
--- a/drivers/net/wireless/realtek/rtw88/main.h
+++ b/drivers/net/wireless/realtek/rtw88/main.h
@@ -871,6 +871,10 @@ struct rtw_chip_ops {
bool is_tx2_path);
void (*config_txrx_mode)(struct rtw_dev *rtwdev, u8 tx_path,
u8 rx_path, bool is_tx2_path);
+ /* for USB/SDIO only */
+ void (*fill_txdesc_checksum)(struct rtw_dev *rtwdev,
+ struct rtw_tx_pkt_info *pkt_info,
+ u8 *txdesc);

/* for coex */
void (*coex_set_init)(struct rtw_dev *rtwdev);
diff --git a/drivers/net/wireless/realtek/rtw88/reg.h b/drivers/net/wireless/realtek/rtw88/reg.h
index 03bd8dc53f72a..8852b24d6c2ac 100644
--- a/drivers/net/wireless/realtek/rtw88/reg.h
+++ b/drivers/net/wireless/realtek/rtw88/reg.h
@@ -184,6 +184,7 @@
#define BIT_TXDMA_VIQ_MAP(x) \
(((x) & BIT_MASK_TXDMA_VIQ_MAP) << BIT_SHIFT_TXDMA_VIQ_MAP)
#define REG_TXDMA_PQ_MAP 0x010C
+#define BIT_RXDMA_ARBBW_EN BIT(0)
#define BIT_SHIFT_TXDMA_BEQ_MAP 8
#define BIT_MASK_TXDMA_BEQ_MAP 0x3
#define BIT_TXDMA_BEQ_MAP(x) \
diff --git a/drivers/net/wireless/realtek/rtw88/tx.h b/drivers/net/wireless/realtek/rtw88/tx.h
index 8419603adce4a..a2f3ac326041b 100644
--- a/drivers/net/wireless/realtek/rtw88/tx.h
+++ b/drivers/net/wireless/realtek/rtw88/tx.h
@@ -71,6 +71,14 @@
le32p_replace_bits((__le32 *)(txdesc) + 0x03, value, BIT(15))
#define SET_TX_DESC_BT_NULL(txdesc, value) \
le32p_replace_bits((__le32 *)(txdesc) + 0x02, value, BIT(23))
+#define SET_TX_DESC_TXDESC_CHECKSUM(txdesc, value) \
+ le32p_replace_bits((__le32 *)(txdesc) + 0x07, value, GENMASK(15, 0))
+#define SET_TX_DESC_DMA_TXAGG_NUM(txdesc, value) \
+ le32p_replace_bits((__le32 *)(txdesc) + 0x07, value, GENMASK(31, 24))
+#define GET_TX_DESC_PKT_OFFSET(txdesc) \
+ le32_get_bits(*((__le32 *)(txdesc) + 0x01), GENMASK(28, 24))
+#define GET_TX_DESC_QSEL(txdesc) \
+ le32_get_bits(*((__le32 *)(txdesc) + 0x01), GENMASK(12, 8))

enum rtw_tx_desc_queue_select {
TX_DESC_QSEL_TID0 = 0,
@@ -123,4 +131,27 @@ rtw_tx_write_data_h2c_get(struct rtw_dev *rtwdev,
struct rtw_tx_pkt_info *pkt_info,
u8 *buf, u32 size);

+static inline
+void fill_txdesc_checksum_common(u8 *txdesc, size_t words)
+{
+ __le16 chksum = 0;
+ __le16 *data = (__le16 *)(txdesc);
+
+ SET_TX_DESC_TXDESC_CHECKSUM(txdesc, 0x0000);
+
+ while (words--)
+ chksum ^= *data++;
+
+ SET_TX_DESC_TXDESC_CHECKSUM(txdesc, __le16_to_cpu(chksum));
+}
+
+static inline void rtw_tx_fill_txdesc_checksum(struct rtw_dev *rtwdev,
+ struct rtw_tx_pkt_info *pkt_info,
+ u8 *txdesc)
+{
+ const struct rtw_chip_info *chip = rtwdev->chip;
+
+ chip->ops->fill_txdesc_checksum(rtwdev, pkt_info, txdesc);
+}
+
#endif
diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c
new file mode 100644
index 0000000000000..4a12934d20712
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/usb.c
@@ -0,0 +1,918 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) 2018-2019 Realtek Corporation
+ */
+
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/mutex.h>
+#include "main.h"
+#include "debug.h"
+#include "reg.h"
+#include "tx.h"
+#include "rx.h"
+#include "fw.h"
+#include "ps.h"
+#include "usb.h"
+
+#define RTW_USB_MAX_RXQ_LEN 128
+
+struct rtw_usb_txcb {
+ struct rtw_dev *rtwdev;
+ struct sk_buff_head tx_ack_queue;
+};
+
+static void rtw_usb_fill_tx_checksum(struct rtw_usb *rtwusb,
+ struct sk_buff *skb, int agg_num)
+{
+ struct rtw_dev *rtwdev = rtwusb->rtwdev;
+ struct rtw_tx_pkt_info pkt_info;
+
+ SET_TX_DESC_DMA_TXAGG_NUM(skb->data, agg_num);
+ pkt_info.pkt_offset = GET_TX_DESC_PKT_OFFSET(skb->data);
+ rtw_tx_fill_txdesc_checksum(rtwdev, &pkt_info, skb->data);
+}
+
+static u32 rtw_usb_read(struct rtw_dev *rtwdev, u32 addr, u16 len)
+{
+ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
+ struct usb_device *udev = rtwusb->udev;
+ __le32 *data;
+ unsigned long flags;
+ int ret;
+ static int count;
+
+ spin_lock_irqsave(&rtwusb->usb_lock, flags);
+
+ rtwusb->usb_data_index++;
+ rtwusb->usb_data_index &= (RTW_USB_MAX_RXTX_COUNT - 1);
+
+ spin_unlock_irqrestore(&rtwusb->usb_lock, flags);
+
+ data = &rtwusb->usb_data[rtwusb->usb_data_index];
+
+ ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+ RTW_USB_CMD_REQ, RTW_USB_CMD_READ, addr,
+ RTW_USB_VENQT_CMD_IDX, data, len, 1000);
+ if (ret < 0 && ret != -ENODEV && count++ < 4)
+ rtw_err(rtwdev, "read register 0x%x failed with %d\n",
+ addr, ret);
+
+ return le32_to_cpu(*data);
+}
+
+static u8 rtw_usb_read8(struct rtw_dev *rtwdev, u32 addr)
+{
+ return (u8)rtw_usb_read(rtwdev, addr, 1);
+}
+
+static u16 rtw_usb_read16(struct rtw_dev *rtwdev, u32 addr)
+{
+ return (u16)rtw_usb_read(rtwdev, addr, 2);
+}
+
+static u32 rtw_usb_read32(struct rtw_dev *rtwdev, u32 addr)
+{
+ return (u32)rtw_usb_read(rtwdev, addr, 4);
+}
+
+static void rtw_usb_write(struct rtw_dev *rtwdev, u32 addr, u32 val, int len)
+{
+ struct rtw_usb *rtwusb = (struct rtw_usb *)rtwdev->priv;
+ struct usb_device *udev = rtwusb->udev;
+ unsigned long flags;
+ __le32 *data;
+ int ret;
+ static int count;
+
+ spin_lock_irqsave(&rtwusb->usb_lock, flags);
+
+ rtwusb->usb_data_index++;
+ rtwusb->usb_data_index &= (RTW_USB_MAX_RXTX_COUNT - 1);
+
+ spin_unlock_irqrestore(&rtwusb->usb_lock, flags);
+
+ data = &rtwusb->usb_data[rtwusb->usb_data_index];
+
+ *data = cpu_to_le32(val);
+
+ ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ RTW_USB_CMD_REQ, RTW_USB_CMD_WRITE,
+ addr, 0, data, len, 30000);
+ if (ret < 0 && ret != -ENODEV && count++ < 4)
+ rtw_err(rtwdev, "write register 0x%x failed with %d\n",
+ addr, ret);
+}
+
+static void rtw_usb_write8(struct rtw_dev *rtwdev, u32 addr, u8 val)
+{
+ rtw_usb_write(rtwdev, addr, val, 1);
+}
+
+static void rtw_usb_write16(struct rtw_dev *rtwdev, u32 addr, u16 val)
+{
+ rtw_usb_write(rtwdev, addr, val, 2);
+}
+
+static void rtw_usb_write32(struct rtw_dev *rtwdev, u32 addr, u32 val)
+{
+ rtw_usb_write(rtwdev, addr, val, 4);
+}
+
+static int rtw_usb_parse(struct rtw_dev *rtwdev,
+ struct usb_interface *interface)
+{
+ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
+ struct usb_host_interface *host_interface = &interface->altsetting[0];
+ struct usb_interface_descriptor *interface_desc = &host_interface->desc;
+ struct usb_endpoint_descriptor *endpoint;
+ struct usb_device *usbd = interface_to_usbdev(interface);
+ int num_out_pipes = 0;
+ int i;
+ u8 num;
+
+ for (i = 0; i < interface_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->pipe_in) {
+ rtw_err(rtwdev, "IN pipes overflow\n");
+ return -EINVAL;
+ }
+
+ rtwusb->pipe_in = num;
+ }
+
+ if (usb_endpoint_dir_in(endpoint) &&
+ usb_endpoint_xfer_int(endpoint)) {
+ if (rtwusb->pipe_interrupt) {
+ rtw_err(rtwdev, "INT pipes overflow\n");
+ return -EINVAL;
+ }
+
+ rtwusb->pipe_interrupt = num;
+ }
+
+ if (usb_endpoint_dir_out(endpoint) &&
+ usb_endpoint_xfer_bulk(endpoint)) {
+ if (num_out_pipes >= ARRAY_SIZE(rtwusb->out_ep)) {
+ rtw_err(rtwdev, "OUT pipes overflow\n");
+ return -EINVAL;
+ }
+
+ rtwusb->out_ep[num_out_pipes++] = num;
+ }
+ }
+
+ switch (usbd->speed) {
+ case USB_SPEED_LOW:
+ case USB_SPEED_FULL:
+ rtwusb->bulkout_size = RTW_USB_FULL_SPEED_BULK_SIZE;
+ break;
+ case USB_SPEED_HIGH:
+ rtwusb->bulkout_size = RTW_USB_HIGH_SPEED_BULK_SIZE;
+ break;
+ case USB_SPEED_SUPER:
+ rtwusb->bulkout_size = RTW_USB_SUPER_SPEED_BULK_SIZE;
+ break;
+ default:
+ rtw_err(rtwdev, "failed to detect usb speed\n");
+ return -EINVAL;
+ }
+
+ rtwdev->hci.bulkout_num = num_out_pipes;
+
+ switch (num_out_pipes) {
+ case 4:
+ case 3:
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID0] = 2;
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID1] = 2;
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID2] = 2;
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID3] = 2;
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID4] = 1;
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID5] = 1;
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID6] = 0;
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID7] = 0;
+ break;
+ case 2:
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID0] = 1;
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID1] = 1;
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID2] = 1;
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID3] = 1;
+ break;
+ case 1:
+ break;
+ default:
+ rtw_err(rtwdev, "failed to get out_pipes(%d)\n", num_out_pipes);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void rtw_usb_write_port_tx_complete(struct urb *urb)
+{
+ struct rtw_usb_txcb *txcb = urb->context;
+ struct rtw_dev *rtwdev = txcb->rtwdev;
+ struct ieee80211_hw *hw = rtwdev->hw;
+
+ while (true) {
+ struct sk_buff *skb = skb_dequeue(&txcb->tx_ack_queue);
+ struct ieee80211_tx_info *info;
+ struct rtw_usb_tx_data *tx_data;
+
+ if (!skb)
+ break;
+
+ info = IEEE80211_SKB_CB(skb);
+ tx_data = rtw_usb_get_tx_data(skb);
+
+ /* enqueue to wait for tx report */
+ if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) {
+ rtw_tx_report_enqueue(rtwdev, skb, tx_data->sn);
+ continue;
+ }
+
+ /* always ACK for others, then they won't be marked as drop */
+ ieee80211_tx_info_clear_status(info);
+ 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(hw, skb);
+ }
+
+ kfree(txcb);
+}
+
+static int qsel_to_ep(struct rtw_usb *rtwusb, unsigned int qsel)
+{
+ if (qsel >= ARRAY_SIZE(rtwusb->qsel_to_ep))
+ return 0;
+
+ return rtwusb->qsel_to_ep[qsel];
+}
+
+static int rtw_usb_write_port(struct rtw_dev *rtwdev, u8 qsel, struct sk_buff *skb,
+ usb_complete_t cb, void *context)
+{
+ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
+ struct usb_device *usbd = rtwusb->udev;
+ struct urb *urb;
+ unsigned int pipe;
+ int ret;
+ int ep = qsel_to_ep(rtwusb, qsel);
+
+ pipe = usb_sndbulkpipe(usbd, rtwusb->out_ep[ep]);
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!urb)
+ return -ENOMEM;
+
+ usb_fill_bulk_urb(urb, usbd, pipe, skb->data, skb->len, cb, context);
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
+
+ usb_free_urb(urb);
+
+ return ret;
+}
+
+static bool rtw_usb_tx_agg_skb(struct rtw_usb *rtwusb, struct sk_buff_head *list)
+{
+ struct rtw_dev *rtwdev = rtwusb->rtwdev;
+ struct rtw_usb_txcb *txcb;
+ struct sk_buff *skb_head;
+ struct sk_buff *skb_iter;
+ u8 *data_ptr;
+ int agg_num = 0;
+ unsigned int align_next = 0;
+
+ if (skb_queue_empty(list))
+ return false;
+
+ txcb = kmalloc(sizeof(*txcb), GFP_ATOMIC);
+ if (!txcb)
+ return false;
+
+ txcb->rtwdev = rtwdev;
+ skb_queue_head_init(&txcb->tx_ack_queue);
+
+ skb_iter = skb_dequeue(list);
+
+ if (skb_queue_empty(list)) {
+ skb_head = skb_iter;
+ goto queue;
+ }
+
+ skb_head = dev_alloc_skb(RTW_USB_MAX_XMITBUF_SZ);
+ if (!skb_head) {
+ skb_head = skb_iter;
+ goto queue;
+ }
+
+ data_ptr = skb_head->data;
+
+ while (skb_iter) {
+ unsigned long flags;
+
+ memcpy(data_ptr, skb_iter->data, skb_iter->len);
+ skb_put(skb_head, skb_iter->len + align_next);
+
+ align_next = ALIGN(skb_iter->len, 8) - skb_iter->len;
+ data_ptr += skb_iter->len + align_next;
+
+ agg_num++;
+
+ skb_queue_tail(&txcb->tx_ack_queue, skb_iter);
+
+ spin_lock_irqsave(&list->lock, flags);
+
+ skb_iter = skb_peek(list);
+
+ if (skb_iter && skb_iter->len + skb_head->len <= RTW_USB_MAX_XMITBUF_SZ)
+ __skb_unlink(skb_iter, list);
+ else
+ skb_iter = NULL;
+ spin_unlock_irqrestore(&list->lock, flags);
+ }
+
+ if (agg_num > 1)
+ rtw_usb_fill_tx_checksum(rtwusb, skb_head, agg_num);
+
+queue:
+ skb_queue_tail(&txcb->tx_ack_queue, skb_head);
+
+ rtw_usb_write_port(rtwdev, GET_TX_DESC_QSEL(skb_head->data), skb_head,
+ rtw_usb_write_port_tx_complete, txcb);
+
+ return true;
+}
+
+static void rtw_usb_tx_handler(struct work_struct *work)
+{
+ struct rtw_usb *rtwusb = container_of(work, struct rtw_usb, tx_work);
+ int i, limit;
+
+ for (i = ARRAY_SIZE(rtwusb->tx_queue) - 1; i >= 0; i--) {
+ for (limit = 0; limit < 200; limit++) {
+ struct sk_buff_head *list = &rtwusb->tx_queue[i];
+
+ if (!rtw_usb_tx_agg_skb(rtwusb, list))
+ break;
+ }
+ }
+}
+
+static void rtw_usb_tx_queue_purge(struct rtw_usb *rtwusb)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(rtwusb->tx_queue); i++)
+ skb_queue_purge(&rtwusb->tx_queue[i]);
+}
+
+static void rtw_usb_write_port_complete(struct urb *urb)
+{
+ struct sk_buff *skb = urb->context;
+
+ dev_kfree_skb_any(skb);
+}
+
+static int rtw_usb_write_data(struct rtw_dev *rtwdev,
+ struct rtw_tx_pkt_info *pkt_info,
+ u8 *buf)
+{
+ const struct rtw_chip_info *chip = rtwdev->chip;
+ struct sk_buff *skb;
+ unsigned int desclen, headsize, size;
+ u8 qsel;
+ int ret = 0;
+ struct rtw_usb *rtwusb;
+
+ rtwusb = rtw_get_usb_priv(rtwdev);
+
+ size = pkt_info->tx_pkt_size;
+ qsel = pkt_info->qsel;
+ desclen = chip->tx_pkt_desc_sz;
+ headsize = pkt_info->offset ? pkt_info->offset : desclen;
+
+ skb = dev_alloc_skb(headsize + size);
+ if (unlikely(!skb))
+ return -ENOMEM;
+
+ skb_reserve(skb, headsize);
+ skb_put_data(skb, buf, size);
+ skb_push(skb, headsize);
+ memset(skb->data, 0, headsize);
+ rtw_tx_fill_tx_desc(pkt_info, skb);
+ rtw_tx_fill_txdesc_checksum(rtwdev, pkt_info, skb->data);
+
+ ret = rtw_usb_write_port(rtwdev, qsel, skb,
+ rtw_usb_write_port_complete, skb);
+ if (unlikely(ret))
+ rtw_err(rtwdev, "failed to do USB write, ret=%d\n", ret);
+
+ return ret;
+}
+
+static int rtw_usb_write_data_rsvd_page(struct rtw_dev *rtwdev, u8 *buf,
+ u32 size)
+{
+ const struct rtw_chip_info *chip = rtwdev->chip;
+ struct rtw_usb *rtwusb;
+ struct rtw_tx_pkt_info pkt_info = {0};
+ u32 len, desclen;
+
+ rtwusb = rtw_get_usb_priv(rtwdev);
+
+ pkt_info.tx_pkt_size = size;
+ pkt_info.qsel = TX_DESC_QSEL_BEACON;
+
+ desclen = chip->tx_pkt_desc_sz;
+ len = desclen + size;
+ if (len % rtwusb->bulkout_size == 0) {
+ len += RTW_USB_PACKET_OFFSET_SZ;
+ pkt_info.offset = desclen + RTW_USB_PACKET_OFFSET_SZ;
+ pkt_info.pkt_offset = 1;
+ } else {
+ pkt_info.offset = desclen;
+ }
+
+ return rtw_usb_write_data(rtwdev, &pkt_info, buf);
+}
+
+static int rtw_usb_write_data_h2c(struct rtw_dev *rtwdev, u8 *buf, u32 size)
+{
+ struct rtw_tx_pkt_info pkt_info = {0};
+
+ pkt_info.tx_pkt_size = size;
+ pkt_info.qsel = TX_DESC_QSEL_H2C;
+
+ return rtw_usb_write_data(rtwdev, &pkt_info, buf);
+}
+
+static u8 rtw_usb_tx_queue_mapping_to_qsel(struct sk_buff *skb)
+{
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ __le16 fc = hdr->frame_control;
+ u8 qsel;
+
+ if (unlikely(ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)))
+ qsel = TX_DESC_QSEL_MGMT;
+ else if (skb_get_queue_mapping(skb) <= IEEE80211_AC_BK)
+ qsel = skb->priority;
+ else
+ qsel = TX_DESC_QSEL_BEACON;
+
+ return qsel;
+}
+
+static int rtw_usb_tx_write(struct rtw_dev *rtwdev,
+ struct rtw_tx_pkt_info *pkt_info,
+ struct sk_buff *skb)
+{
+ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
+ const struct rtw_chip_info *chip = rtwdev->chip;
+ struct rtw_usb_tx_data *tx_data;
+ u8 *pkt_desc;
+ int ep;
+
+ pkt_desc = skb_push(skb, chip->tx_pkt_desc_sz);
+ memset(pkt_desc, 0, chip->tx_pkt_desc_sz);
+ pkt_info->qsel = rtw_usb_tx_queue_mapping_to_qsel(skb);
+ ep = qsel_to_ep(rtwusb, pkt_info->qsel);
+ rtw_tx_fill_tx_desc(pkt_info, skb);
+ rtw_tx_fill_txdesc_checksum(rtwdev, pkt_info, skb->data);
+ tx_data = rtw_usb_get_tx_data(skb);
+ tx_data->sn = pkt_info->sn;
+
+ skb_queue_tail(&rtwusb->tx_queue[ep], skb);
+
+ return 0;
+}
+
+static void rtw_usb_tx_kick_off(struct rtw_dev *rtwdev)
+{
+ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
+
+ queue_work(rtwusb->txwq, &rtwusb->tx_work);
+}
+
+static void rtw_usb_rx_handler(struct work_struct *work)
+{
+ struct rtw_usb *rtwusb = container_of(work, struct rtw_usb, rx_work);
+ struct rtw_dev *rtwdev = rtwusb->rtwdev;
+ const struct rtw_chip_info *chip = rtwdev->chip;
+ struct rtw_rx_pkt_stat pkt_stat;
+ struct ieee80211_rx_status rx_status;
+ struct sk_buff *skb;
+ u32 pkt_desc_sz = chip->rx_pkt_desc_sz;
+ u32 pkt_offset;
+ u8 *rx_desc;
+ int limit;
+
+ for (limit = 0; limit < 200; limit++) {
+ skb = skb_dequeue(&rtwusb->rx_queue);
+ if (!skb)
+ break;
+
+ rx_desc = skb->data;
+ chip->ops->query_rx_desc(rtwdev, rx_desc, &pkt_stat,
+ &rx_status);
+ pkt_offset = pkt_desc_sz + pkt_stat.drv_info_sz +
+ pkt_stat.shift;
+
+ if (pkt_stat.is_c2h) {
+ skb_put(skb, pkt_stat.pkt_len + pkt_offset);
+ rtw_fw_c2h_cmd_rx_irqsafe(rtwdev, pkt_offset, skb);
+ continue;
+ }
+
+ if (skb_queue_len(&rtwusb->rx_queue) >= RTW_USB_MAX_RXQ_LEN) {
+ rtw_err(rtwdev, "failed to get rx_queue, overflow\n");
+ dev_kfree_skb_any(skb);
+ continue;
+ }
+
+ skb_put(skb, pkt_stat.pkt_len);
+ skb_reserve(skb, pkt_offset);
+ memcpy(skb->cb, &rx_status, sizeof(rx_status));
+ ieee80211_rx_irqsafe(rtwdev->hw, skb);
+ }
+}
+
+static void rtw_usb_read_port_complete(struct urb *urb);
+
+static void rtw_usb_rx_resubmit(struct rtw_usb *rtwusb, struct rx_usb_ctrl_block *rxcb)
+{
+ struct rtw_dev *rtwdev = rtwusb->rtwdev;
+ int error;
+
+ rxcb->rx_skb = alloc_skb(RTW_USB_MAX_RECVBUF_SZ, GFP_ATOMIC);
+ if (!rxcb->rx_skb)
+ return;
+
+ usb_fill_bulk_urb(rxcb->rx_urb, rtwusb->udev,
+ usb_rcvbulkpipe(rtwusb->udev, rtwusb->pipe_in),
+ rxcb->rx_skb->data, RTW_USB_MAX_RECVBUF_SZ,
+ rtw_usb_read_port_complete, rxcb);
+
+ error = usb_submit_urb(rxcb->rx_urb, GFP_ATOMIC);
+ if (error) {
+ kfree_skb(rxcb->rx_skb);
+ if (error != -ENODEV)
+ rtw_err(rtwdev, "Err sending rx data urb %d\n",
+ error);
+ }
+}
+
+static void rtw_usb_read_port_complete(struct urb *urb)
+{
+ struct rx_usb_ctrl_block *rxcb = urb->context;
+ struct rtw_dev *rtwdev = rxcb->rtwdev;
+ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
+ struct sk_buff *skb = rxcb->rx_skb;
+
+ if (urb->status == 0) {
+ if (urb->actual_length >= RTW_USB_MAX_RECVBUF_SZ ||
+ urb->actual_length < 24) {
+ rtw_err(rtwdev, "failed to get urb length:%d\n",
+ urb->actual_length);
+ if (skb)
+ dev_kfree_skb_any(skb);
+ } else {
+ skb_queue_tail(&rtwusb->rx_queue, skb);
+ queue_work(rtwusb->rxwq, &rtwusb->rx_work);
+ }
+ rtw_usb_rx_resubmit(rtwusb, rxcb);
+ } else {
+ switch (urb->status) {
+ case -EINVAL:
+ case -EPIPE:
+ case -ENODEV:
+ case -ESHUTDOWN:
+ case -ENOENT:
+ case -EPROTO:
+ case -EILSEQ:
+ case -ETIME:
+ case -ECOMM:
+ case -EOVERFLOW:
+ case -EINPROGRESS:
+ break;
+ default:
+ rtw_err(rtwdev, "status %d\n", urb->status);
+ break;
+ }
+ if (skb)
+ dev_kfree_skb_any(skb);
+ }
+}
+
+static void rtw_usb_cancel_rx_bufs(struct rtw_usb *rtwusb)
+{
+ struct rx_usb_ctrl_block *rxcb;
+ int i;
+
+ for (i = 0; i < RTW_USB_RXCB_NUM; i++) {
+ rxcb = &rtwusb->rx_cb[i];
+ if (rxcb->rx_urb)
+ usb_kill_urb(rxcb->rx_urb);
+ }
+}
+
+static void rtw_usb_free_rx_bufs(struct rtw_usb *rtwusb)
+{
+ struct rx_usb_ctrl_block *rxcb;
+ int i;
+
+ for (i = 0; i < RTW_USB_RXCB_NUM; i++) {
+ rxcb = &rtwusb->rx_cb[i];
+ if (rxcb->rx_urb) {
+ usb_kill_urb(rxcb->rx_urb);
+ usb_free_urb(rxcb->rx_urb);
+ }
+ }
+}
+
+static int rtw_usb_alloc_rx_bufs(struct rtw_usb *rtwusb)
+{
+ int i;
+
+ for (i = 0; i < RTW_USB_RXCB_NUM; i++) {
+ struct rx_usb_ctrl_block *rxcb = &rtwusb->rx_cb[i];
+
+ rxcb->n = i;
+ rxcb->rtwdev = rtwusb->rtwdev;
+ rxcb->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!rxcb->rx_urb)
+ goto err;
+ }
+
+ return 0;
+err:
+ rtw_usb_free_rx_bufs(rtwusb);
+ return -ENOMEM;
+}
+
+static int rtw_usb_setup(struct rtw_dev *rtwdev)
+{
+ /* empty function for rtw_hci_ops */
+ return 0;
+}
+
+static int rtw_usb_start(struct rtw_dev *rtwdev)
+{
+ return 0;
+}
+
+static void rtw_usb_stop(struct rtw_dev *rtwdev)
+{
+}
+
+static void rtw_usb_deep_ps(struct rtw_dev *rtwdev, bool enter)
+{
+ /* empty function for rtw_hci_ops */
+}
+
+static void rtw_usb_link_ps(struct rtw_dev *rtwdev, bool enter)
+{
+ /* empty function for rtw_hci_ops */
+}
+
+static void rtw_usb_interface_cfg(struct rtw_dev *rtwdev)
+{
+ /* empty function for rtw_hci_ops */
+}
+
+static struct rtw_hci_ops rtw_usb_ops = {
+ .tx_write = rtw_usb_tx_write,
+ .tx_kick_off = rtw_usb_tx_kick_off,
+ .setup = rtw_usb_setup,
+ .start = rtw_usb_start,
+ .stop = rtw_usb_stop,
+ .deep_ps = rtw_usb_deep_ps,
+ .link_ps = rtw_usb_link_ps,
+ .interface_cfg = rtw_usb_interface_cfg,
+
+ .write8 = rtw_usb_write8,
+ .write16 = rtw_usb_write16,
+ .write32 = rtw_usb_write32,
+ .read8 = rtw_usb_read8,
+ .read16 = rtw_usb_read16,
+ .read32 = rtw_usb_read32,
+
+ .write_data_rsvd_page = rtw_usb_write_data_rsvd_page,
+ .write_data_h2c = rtw_usb_write_data_h2c,
+};
+
+static int rtw_usb_init_rx(struct rtw_dev *rtwdev)
+{
+ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
+ int i;
+
+ rtwusb->rxwq = create_singlethread_workqueue("rtw88_usb: rx wq");
+ if (!rtwusb->rxwq) {
+ rtw_err(rtwdev, "failed to create RX work queue\n");
+ return -ENOMEM;
+ }
+
+ skb_queue_head_init(&rtwusb->rx_queue);
+
+ INIT_WORK(&rtwusb->rx_work, rtw_usb_rx_handler);
+
+ for (i = 0; i < RTW_USB_RXCB_NUM; i++) {
+ struct rx_usb_ctrl_block *rxcb = &rtwusb->rx_cb[i];
+
+ rtw_usb_rx_resubmit(rtwusb, rxcb);
+ }
+
+ return 0;
+}
+
+static void rtw_usb_deinit_rx(struct rtw_dev *rtwdev)
+{
+ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
+
+ skb_queue_purge(&rtwusb->rx_queue);
+
+ flush_workqueue(rtwusb->rxwq);
+ destroy_workqueue(rtwusb->rxwq);
+}
+
+static int rtw_usb_init_tx(struct rtw_dev *rtwdev)
+{
+ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
+ int i;
+
+ rtwusb->txwq = create_singlethread_workqueue("rtw88_usb: tx wq");
+ if (!rtwusb->txwq) {
+ rtw_err(rtwdev, "failed to create TX work queue\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(rtwusb->tx_queue); i++)
+ skb_queue_head_init(&rtwusb->tx_queue[i]);
+
+ INIT_WORK(&rtwusb->tx_work, rtw_usb_tx_handler);
+
+ return 0;
+}
+
+static void rtw_usb_deinit_tx(struct rtw_dev *rtwdev)
+{
+ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
+
+ rtw_usb_tx_queue_purge(rtwusb);
+ flush_workqueue(rtwusb->txwq);
+ destroy_workqueue(rtwusb->txwq);
+}
+
+static int rtw_usb_intf_init(struct rtw_dev *rtwdev,
+ struct usb_interface *intf)
+{
+ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
+ struct usb_device *udev = usb_get_dev(interface_to_usbdev(intf));
+ int ret;
+
+ rtwusb->udev = udev;
+ ret = rtw_usb_parse(rtwdev, intf);
+ if (ret)
+ return ret;
+
+ rtwusb->usb_data = kcalloc(RTW_USB_MAX_RXTX_COUNT, sizeof(u32),
+ GFP_KERNEL);
+ if (!rtwusb->usb_data)
+ return -ENOMEM;
+
+ usb_set_intfdata(intf, rtwdev->hw);
+
+ SET_IEEE80211_DEV(rtwdev->hw, &intf->dev);
+ spin_lock_init(&rtwusb->usb_lock);
+
+ return 0;
+}
+
+static void rtw_usb_intf_deinit(struct rtw_dev *rtwdev,
+ struct usb_interface *intf)
+{
+ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
+
+ usb_put_dev(rtwusb->udev);
+ usb_set_intfdata(intf, NULL);
+}
+
+int rtw_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+ struct rtw_dev *rtwdev;
+ struct ieee80211_hw *hw;
+ struct rtw_usb *rtwusb;
+ int drv_data_size;
+ int ret;
+
+ drv_data_size = sizeof(struct rtw_dev) + sizeof(struct rtw_usb);
+ hw = ieee80211_alloc_hw(drv_data_size, &rtw_ops);
+ if (!hw)
+ return -ENOMEM;
+
+ rtwdev = hw->priv;
+ rtwdev->hw = hw;
+ rtwdev->dev = &intf->dev;
+ rtwdev->chip = (struct rtw_chip_info *)id->driver_info;
+ rtwdev->hci.ops = &rtw_usb_ops;
+ rtwdev->hci.type = RTW_HCI_TYPE_USB;
+
+ rtwusb = rtw_get_usb_priv(rtwdev);
+ rtwusb->rtwdev = rtwdev;
+
+ ret = rtw_usb_alloc_rx_bufs(rtwusb);
+ if (ret)
+ return ret;
+
+ ret = rtw_core_init(rtwdev);
+ if (ret)
+ goto err_release_hw;
+
+ ret = rtw_usb_intf_init(rtwdev, intf);
+ if (ret) {
+ rtw_err(rtwdev, "failed to init USB interface\n");
+ goto err_deinit_core;
+ }
+
+ ret = rtw_usb_init_tx(rtwdev);
+ if (ret) {
+ rtw_err(rtwdev, "failed to init USB TX\n");
+ goto err_destroy_usb;
+ }
+
+ ret = rtw_usb_init_rx(rtwdev);
+ if (ret) {
+ rtw_err(rtwdev, "failed to init USB RX\n");
+ goto err_destroy_txwq;
+ }
+
+ ret = rtw_chip_info_setup(rtwdev);
+ if (ret) {
+ rtw_err(rtwdev, "failed to setup chip information\n");
+ goto err_destroy_rxwq;
+ }
+
+ ret = rtw_register_hw(rtwdev, rtwdev->hw);
+ if (ret) {
+ rtw_err(rtwdev, "failed to register hw\n");
+ goto err_destroy_rxwq;
+ }
+
+ return 0;
+
+err_destroy_rxwq:
+ rtw_usb_deinit_rx(rtwdev);
+
+err_destroy_txwq:
+ rtw_usb_deinit_tx(rtwdev);
+
+err_destroy_usb:
+ rtw_usb_intf_deinit(rtwdev, intf);
+
+err_deinit_core:
+ rtw_core_deinit(rtwdev);
+
+err_release_hw:
+ ieee80211_free_hw(hw);
+
+ return ret;
+}
+EXPORT_SYMBOL(rtw_usb_probe);
+
+void rtw_usb_disconnect(struct usb_interface *intf)
+{
+ struct ieee80211_hw *hw = usb_get_intfdata(intf);
+ struct rtw_dev *rtwdev;
+ struct rtw_usb *rtwusb;
+
+ if (!hw)
+ return;
+
+ rtwdev = hw->priv;
+ rtwusb = rtw_get_usb_priv(rtwdev);
+
+ rtw_usb_cancel_rx_bufs(rtwusb);
+
+ rtw_unregister_hw(rtwdev, hw);
+ rtw_usb_deinit_tx(rtwdev);
+ rtw_usb_deinit_rx(rtwdev);
+
+ if (rtwusb->udev->state != USB_STATE_NOTATTACHED)
+ usb_reset_device(rtwusb->udev);
+
+ rtw_usb_free_rx_bufs(rtwusb);
+
+ rtw_usb_intf_deinit(rtwdev, intf);
+ rtw_core_deinit(rtwdev);
+ ieee80211_free_hw(hw);
+}
+EXPORT_SYMBOL(rtw_usb_disconnect);
+
+MODULE_AUTHOR("Realtek Corporation");
+MODULE_DESCRIPTION("Realtek 802.11ac wireless USB driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/realtek/rtw88/usb.h b/drivers/net/wireless/realtek/rtw88/usb.h
new file mode 100644
index 0000000000000..e26f8afb09f29
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/usb.h
@@ -0,0 +1,107 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2018-2019 Realtek Corporation
+ */
+
+#ifndef __RTW_USB_H_
+#define __RTW_USB_H_
+
+#define FW_8192C_START_ADDRESS 0x1000
+#define FW_8192C_END_ADDRESS 0x5fff
+
+#define RTW_USB_MAX_RXTX_COUNT 128
+#define RTW_USB_VENQT_MAX_BUF_SIZE 254
+#define MAX_USBCTRL_VENDORREQ_TIMES 10
+
+#define RTW_USB_CMD_READ 0xc0
+#define RTW_USB_CMD_WRITE 0x40
+#define RTW_USB_CMD_REQ 0x05
+
+#define RTW_USB_VENQT_CMD_IDX 0x00
+
+#define RTW_USB_SUPER_SPEED_BULK_SIZE 1024
+#define RTW_USB_HIGH_SPEED_BULK_SIZE 512
+#define RTW_USB_FULL_SPEED_BULK_SIZE 64
+
+#define RTW_USB_TX_SEL_HQ BIT(0)
+#define RTW_USB_TX_SEL_LQ BIT(1)
+#define RTW_USB_TX_SEL_NQ BIT(2)
+#define RTW_USB_TX_SEL_EQ BIT(3)
+
+#define RTW_USB_BULK_IN_ADDR 0x80
+#define RTW_USB_INT_IN_ADDR 0x81
+
+#define RTW_USB_HW_QUEUE_ENTRY 8
+
+#define RTW_USB_PACKET_OFFSET_SZ 8
+#define RTW_USB_MAX_XMITBUF_SZ (1024 * 20)
+#define RTW_USB_MAX_RECVBUF_SZ 32768
+
+#define RTW_USB_RECVBUFF_ALIGN_SZ 8
+
+#define RTW_USB_RXAGG_SIZE 6
+#define RTW_USB_RXAGG_TIMEOUT 10
+
+#define RTW_USB_RXCB_NUM 4
+
+#define RTW_USB_EP_MAX 4
+
+#define TX_DESC_QSEL_MAX 20
+
+#define RTW_USB_VENDOR_ID_REALTEK 0x0bda
+
+static inline struct rtw_usb *rtw_get_usb_priv(struct rtw_dev *rtwdev)
+{
+ return (struct rtw_usb *)rtwdev->priv;
+}
+
+struct rx_usb_ctrl_block {
+ struct rtw_dev *rtwdev;
+ struct urb *rx_urb;
+ struct sk_buff *rx_skb;
+ int n;
+};
+
+struct rtw_usb_tx_data {
+ u8 sn;
+};
+
+struct rtw_usb {
+ struct rtw_dev *rtwdev;
+ struct usb_device *udev;
+
+ /* protects usb_data_index */
+ spinlock_t usb_lock;
+ __le32 *usb_data;
+ unsigned int usb_data_index;
+
+ u32 bulkout_size;
+ u8 pipe_interrupt;
+ u8 pipe_in;
+ u8 out_ep[RTW_USB_EP_MAX];
+ u8 qsel_to_ep[TX_DESC_QSEL_MAX];
+ u8 usb_txagg_num;
+
+ struct workqueue_struct *txwq, *rxwq;
+
+ struct sk_buff_head tx_queue[RTW_USB_EP_MAX];
+ struct work_struct tx_work;
+
+ struct rx_usb_ctrl_block rx_cb[RTW_USB_RXCB_NUM];
+ struct sk_buff_head rx_queue;
+ struct work_struct rx_work;
+};
+
+static inline struct rtw_usb_tx_data *rtw_usb_get_tx_data(struct sk_buff *skb)
+{
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+
+ BUILD_BUG_ON(sizeof(struct rtw_usb_tx_data) >
+ sizeof(info->status.status_driver_data));
+
+ return (struct rtw_usb_tx_data *)info->status.status_driver_data;
+}
+
+int rtw_usb_probe(struct usb_interface *intf, const struct usb_device_id *id);
+void rtw_usb_disconnect(struct usb_interface *intf);
+
+#endif
--
2.30.2

2022-11-22 14:55:09

by Sascha Hauer

[permalink] [raw]
Subject: [PATCH v3 11/11] rtw88: Add rtw8723du chipset support

Add support for the rtw8723du chipset based on
https://github.com/ulli-kroll/rtw88-usb.git

Signed-off-by: Sascha Hauer <[email protected]>
---

Notes:
Changes since v2:
- Re-add this patch, tested on hardware now

Changes since v1:
- Fix txdesc checksum calculation: Unlike other chips this one needs
a chksum = ~chksum at the end
- Fix efuse layout (struct rtw8723de_efuse and struct rtw8723du_efuse need
to be in a union as they are used alternatively)

drivers/net/wireless/realtek/rtw88/Kconfig | 11 ++++++
drivers/net/wireless/realtek/rtw88/Makefile | 3 ++
drivers/net/wireless/realtek/rtw88/rtw8723d.c | 28 +++++++++++++++
drivers/net/wireless/realtek/rtw88/rtw8723d.h | 13 ++++++-
.../net/wireless/realtek/rtw88/rtw8723du.c | 36 +++++++++++++++++++
.../net/wireless/realtek/rtw88/rtw8723du.h | 10 ++++++
6 files changed, 100 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8723du.c
create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8723du.h

diff --git a/drivers/net/wireless/realtek/rtw88/Kconfig b/drivers/net/wireless/realtek/rtw88/Kconfig
index 138289bc5ad0c..651ab56d9c6bd 100644
--- a/drivers/net/wireless/realtek/rtw88/Kconfig
+++ b/drivers/net/wireless/realtek/rtw88/Kconfig
@@ -86,6 +86,17 @@ config RTW88_8723DE

802.11n PCIe wireless network adapter

+config RTW88_8723DU
+ tristate "Realtek 8723DU USB wireless network adapter"
+ depends on USB
+ select RTW88_CORE
+ select RTW88_USB
+ select RTW88_8723D
+ help
+ Select this option will enable support for 8723DU chipset
+
+ 802.11n USB wireless network adapter
+
config RTW88_8821CE
tristate "Realtek 8821CE PCI wireless network adapter"
depends on PCI
diff --git a/drivers/net/wireless/realtek/rtw88/Makefile b/drivers/net/wireless/realtek/rtw88/Makefile
index 06883d7323b05..e0950dbc2565a 100644
--- a/drivers/net/wireless/realtek/rtw88/Makefile
+++ b/drivers/net/wireless/realtek/rtw88/Makefile
@@ -44,6 +44,9 @@ rtw88_8723d-objs := rtw8723d.o rtw8723d_table.o
obj-$(CONFIG_RTW88_8723DE) += rtw88_8723de.o
rtw88_8723de-objs := rtw8723de.o

+obj-$(CONFIG_RTW88_8723DU) += rtw88_8723du.o
+rtw88_8723du-objs := rtw8723du.o
+
obj-$(CONFIG_RTW88_8821C) += rtw88_8821c.o
rtw88_8821c-objs := rtw8821c.o rtw8821c_table.o

diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
index 0a4f770fcbb7e..2d2f768bae2ea 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
@@ -210,6 +210,12 @@ static void rtw8723de_efuse_parsing(struct rtw_efuse *efuse,
ether_addr_copy(efuse->addr, map->e.mac_addr);
}

+static void rtw8723du_efuse_parsing(struct rtw_efuse *efuse,
+ struct rtw8723d_efuse *map)
+{
+ ether_addr_copy(efuse->addr, map->u.mac_addr);
+}
+
static int rtw8723d_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
{
struct rtw_efuse *efuse = &rtwdev->efuse;
@@ -239,6 +245,9 @@ static int rtw8723d_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
case RTW_HCI_TYPE_PCIE:
rtw8723de_efuse_parsing(efuse, map);
break;
+ case RTW_HCI_TYPE_USB:
+ rtw8723du_efuse_parsing(efuse, map);
+ break;
default:
/* unsupported now */
return -ENOTSUPP;
@@ -1945,6 +1954,24 @@ static void rtw8723d_pwr_track(struct rtw_dev *rtwdev)
dm_info->pwr_trk_triggered = false;
}

+static void rtw8723d_fill_txdesc_checksum(struct rtw_dev *rtwdev,
+ struct rtw_tx_pkt_info *pkt_info,
+ u8 *txdesc)
+{
+ size_t words = 32 / 2; /* calculate the first 32 bytes (16 words) */
+ __le16 chksum = 0;
+ __le16 *data = (__le16 *)(txdesc);
+
+ SET_TX_DESC_TXDESC_CHECKSUM(txdesc, 0x0000);
+
+ while (words--)
+ chksum ^= *data++;
+
+ chksum = ~chksum;
+
+ SET_TX_DESC_TXDESC_CHECKSUM(txdesc, __le16_to_cpu(chksum));
+}
+
static struct rtw_chip_ops rtw8723d_ops = {
.phy_set_param = rtw8723d_phy_set_param,
.read_efuse = rtw8723d_read_efuse,
@@ -1965,6 +1992,7 @@ static struct rtw_chip_ops rtw8723d_ops = {
.config_bfee = NULL,
.set_gid_table = NULL,
.cfg_csi_rate = NULL,
+ .fill_txdesc_checksum = rtw8723d_fill_txdesc_checksum,

.coex_set_init = rtw8723d_coex_cfg_init,
.coex_set_ant_switch = NULL,
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.h b/drivers/net/wireless/realtek/rtw88/rtw8723d.h
index 4641f6e047b41..a356318a5c15b 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.h
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.h
@@ -41,6 +41,14 @@ struct rtw8723de_efuse {
u8 sub_device_id[2];
};

+struct rtw8723du_efuse {
+ u8 res4[48]; /* 0xd0 */
+ u8 vender_id[2]; /* 0x100 */
+ u8 product_id[2]; /* 0x102 */
+ u8 usb_option; /* 0x104 */
+ u8 mac_addr[ETH_ALEN]; /* 0x107 */
+};
+
struct rtw8723d_efuse {
__le16 rtl_id;
u8 rsvd[2];
@@ -69,7 +77,10 @@ struct rtw8723d_efuse {
u8 rfe_option;
u8 country_code[2];
u8 res[3];
- struct rtw8723de_efuse e;
+ union {
+ struct rtw8723de_efuse e;
+ struct rtw8723du_efuse u;
+ };
};

extern const struct rtw_chip_info rtw8723d_hw_spec;
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723du.c b/drivers/net/wireless/realtek/rtw88/rtw8723du.c
new file mode 100644
index 0000000000000..d2c8a114d19af
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723du.c
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) 2018-2019 Realtek Corporation
+ */
+
+#include <linux/module.h>
+#include <linux/usb.h>
+#include "main.h"
+#include "rtw8723du.h"
+#include "usb.h"
+
+static const struct usb_device_id rtw_8723du_id_table[] = {
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK,
+ 0xD723,
+ 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8723d_hw_spec) }, /* 8723DU 1*1 */
+ { },
+};
+MODULE_DEVICE_TABLE(usb, rtw_8723du_id_table);
+
+static int rtw8723du_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ return rtw_usb_probe(intf, id);
+}
+
+static struct usb_driver rtw_8723du_driver = {
+ .name = "rtw_8723du",
+ .id_table = rtw_8723du_id_table,
+ .probe = rtw8723du_probe,
+ .disconnect = rtw_usb_disconnect,
+};
+module_usb_driver(rtw_8723du_driver);
+
+MODULE_AUTHOR("Hans Ulli Kroll <[email protected]>");
+MODULE_DESCRIPTION("Realtek 802.11n wireless 8723du driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723du.h b/drivers/net/wireless/realtek/rtw88/rtw8723du.h
new file mode 100644
index 0000000000000..c0ffd621f087d
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/rtw8723du.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2018-2019 Realtek Corporation
+ */
+
+#ifndef __RTW_8723DU_H_
+#define __RTW_8723DU_H_
+
+extern struct rtw_chip_info rtw8723d_hw_spec;
+
+#endif
--
2.30.2

2022-11-22 14:55:29

by Sascha Hauer

[permalink] [raw]
Subject: [PATCH v3 02/11] rtw88: Call rtw_fw_beacon_filter_config() with rtwdev->mutex held

rtw_fw_beacon_filter_config() is called once with rtwdev->mutex held
and once without the mutex held. Call it consistently with rtwdev->mutex
held.

Signed-off-by: Sascha Hauer <[email protected]>
---
drivers/net/wireless/realtek/rtw88/mac80211.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c
index 07578ccc4bab3..776a9a9884b5d 100644
--- a/drivers/net/wireless/realtek/rtw88/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw88/mac80211.c
@@ -487,8 +487,8 @@ static int rtw_ops_sta_remove(struct ieee80211_hw *hw,
{
struct rtw_dev *rtwdev = hw->priv;

- rtw_fw_beacon_filter_config(rtwdev, false, vif);
mutex_lock(&rtwdev->mutex);
+ rtw_fw_beacon_filter_config(rtwdev, false, vif);
rtw_sta_remove(rtwdev, sta, true);
mutex_unlock(&rtwdev->mutex);

--
2.30.2

2022-11-22 14:58:30

by Sascha Hauer

[permalink] [raw]
Subject: [PATCH v3 08/11] rtw88: Add rtw8821cu chipset support

Add support for the rtw8821cu chipset based on
https://github.com/ulli-kroll/rtw88-usb.git

Signed-off-by: Sascha Hauer <[email protected]>
---

Notes:
Changes since v2:
- Fix txdesc checksum calculation. The checksum must be calculated over
a fixed number of words.

drivers/net/wireless/realtek/rtw88/Kconfig | 11 ++++
drivers/net/wireless/realtek/rtw88/Makefile | 3 ++
drivers/net/wireless/realtek/rtw88/rtw8821c.c | 18 +++++++
drivers/net/wireless/realtek/rtw88/rtw8821c.h | 21 ++++++++
.../net/wireless/realtek/rtw88/rtw8821cu.c | 50 +++++++++++++++++++
.../net/wireless/realtek/rtw88/rtw8821cu.h | 10 ++++
6 files changed, 113 insertions(+)
create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8821cu.c
create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8821cu.h

diff --git a/drivers/net/wireless/realtek/rtw88/Kconfig b/drivers/net/wireless/realtek/rtw88/Kconfig
index 1624c5db69bac..2b500dbefbc2d 100644
--- a/drivers/net/wireless/realtek/rtw88/Kconfig
+++ b/drivers/net/wireless/realtek/rtw88/Kconfig
@@ -75,6 +75,17 @@ config RTW88_8821CE

802.11ac PCIe wireless network adapter

+config RTW88_8821CU
+ tristate "Realtek 8821CU USB wireless network adapter"
+ depends on USB
+ select RTW88_CORE
+ select RTW88_USB
+ select RTW88_8821C
+ help
+ Select this option will enable support for 8821CU chipset
+
+ 802.11ac USB wireless network adapter
+
config RTW88_DEBUG
bool "Realtek rtw88 debug support"
depends on RTW88_CORE
diff --git a/drivers/net/wireless/realtek/rtw88/Makefile b/drivers/net/wireless/realtek/rtw88/Makefile
index 9e095f8181483..3c1f08f12e44e 100644
--- a/drivers/net/wireless/realtek/rtw88/Makefile
+++ b/drivers/net/wireless/realtek/rtw88/Makefile
@@ -44,6 +44,9 @@ rtw88_8821c-objs := rtw8821c.o rtw8821c_table.o
obj-$(CONFIG_RTW88_8821CE) += rtw88_8821ce.o
rtw88_8821ce-objs := rtw8821ce.o

+obj-$(CONFIG_RTW88_8821CU) += rtw88_8821cu.o
+rtw88_8821cu-objs := rtw8821cu.o
+
obj-$(CONFIG_RTW88_PCI) += rtw88_pci.o
obj-$(CONFIG_RTW88_USB) += rtw88_usb.o
rtw88_pci-objs := pci.o
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.c b/drivers/net/wireless/realtek/rtw88/rtw8821c.c
index 9afdc5ce86b43..17f800f6efbd0 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8821c.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.c
@@ -26,6 +26,12 @@ static void rtw8821ce_efuse_parsing(struct rtw_efuse *efuse,
ether_addr_copy(efuse->addr, map->e.mac_addr);
}

+static void rtw8821cu_efuse_parsing(struct rtw_efuse *efuse,
+ struct rtw8821c_efuse *map)
+{
+ ether_addr_copy(efuse->addr, map->u.mac_addr);
+}
+
enum rtw8821ce_rf_set {
SWITCH_TO_BTG,
SWITCH_TO_WLG,
@@ -68,6 +74,9 @@ static int rtw8821c_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
case RTW_HCI_TYPE_PCIE:
rtw8821ce_efuse_parsing(efuse, map);
break;
+ case RTW_HCI_TYPE_USB:
+ rtw8821cu_efuse_parsing(efuse, map);
+ break;
default:
/* unsupported now */
return -ENOTSUPP;
@@ -1148,6 +1157,13 @@ static void rtw8821c_phy_cck_pd_set(struct rtw_dev *rtwdev, u8 new_lvl)
dm_info->cck_pd_default + new_lvl * 2);
}

+static void rtw8821c_fill_txdesc_checksum(struct rtw_dev *rtwdev,
+ struct rtw_tx_pkt_info *pkt_info,
+ u8 *txdesc)
+{
+ fill_txdesc_checksum_common(txdesc, 16);
+}
+
static struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8821c[] = {
{0x0086,
RTW_PWR_CUT_ALL_MSK,
@@ -1521,6 +1537,7 @@ static const struct rtw_rfe_def rtw8821c_rfe_defs[] = {
[2] = RTW_DEF_RFE_EXT(8821c, 0, 0, 2),
[4] = RTW_DEF_RFE_EXT(8821c, 0, 0, 2),
[6] = RTW_DEF_RFE(8821c, 0, 0),
+ [34] = RTW_DEF_RFE(8821c, 0, 0),
};

static struct rtw_hw_reg rtw8821c_dig[] = {
@@ -1595,6 +1612,7 @@ static struct rtw_chip_ops rtw8821c_ops = {
.config_bfee = rtw8821c_bf_config_bfee,
.set_gid_table = rtw_bf_set_gid_table,
.cfg_csi_rate = rtw_bf_cfg_csi_rate,
+ .fill_txdesc_checksum = rtw8821c_fill_txdesc_checksum,

.coex_set_init = rtw8821c_coex_cfg_init,
.coex_set_ant_switch = rtw8821c_coex_cfg_ant_switch,
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.h b/drivers/net/wireless/realtek/rtw88/rtw8821c.h
index 2698801fc35d5..1c81260f3a542 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8821c.h
+++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.h
@@ -9,6 +9,26 @@

#define RCR_VHT_ACK BIT(26)

+struct rtw8821cu_efuse {
+ u8 res4[4]; /* 0xd0 */
+ u8 usb_optional_function;
+ u8 res5[0x1e];
+ u8 res6[2];
+ u8 serial[0x0b]; /* 0xf5 */
+ u8 vid; /* 0x100 */
+ u8 res7;
+ u8 pid;
+ u8 res8[4];
+ u8 mac_addr[ETH_ALEN]; /* 0x107 */
+ u8 res9[2];
+ u8 vendor_name[0x07];
+ u8 res10[2];
+ u8 device_name[0x14];
+ u8 res11[0xcf];
+ u8 package_type; /* 0x1fb */
+ u8 res12[0x4];
+};
+
struct rtw8821ce_efuse {
u8 mac_addr[ETH_ALEN]; /* 0xd0 */
u8 vender_id[2];
@@ -73,6 +93,7 @@ struct rtw8821c_efuse {
u8 res[3];
union {
struct rtw8821ce_efuse e;
+ struct rtw8821cu_efuse u;
};
};

diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821cu.c b/drivers/net/wireless/realtek/rtw88/rtw8821cu.c
new file mode 100644
index 0000000000000..f43e200515f5b
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/rtw8821cu.c
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) 2018-2019 Realtek Corporation
+ */
+
+#include <linux/module.h>
+#include <linux/usb.h>
+#include "main.h"
+#include "rtw8821cu.h"
+#include "usb.h"
+
+static const struct usb_device_id rtw_8821cu_id_table[] = {
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xb82b, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xb820, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc821, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc820, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc82a, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc82b, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc811, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8811CU */
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x8811, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8811CU */
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x2006, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* TOTOLINK A650UA v3 */
+ {},
+};
+MODULE_DEVICE_TABLE(usb, rtw_8821cu_id_table);
+
+static int rtw_8821cu_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ return rtw_usb_probe(intf, id);
+}
+
+static struct usb_driver rtw_8821cu_driver = {
+ .name = "rtw_8821cu",
+ .id_table = rtw_8821cu_id_table,
+ .probe = rtw_8821cu_probe,
+ .disconnect = rtw_usb_disconnect,
+};
+module_usb_driver(rtw_8821cu_driver);
+
+MODULE_AUTHOR("Hans Ulli Kroll <[email protected]>");
+MODULE_DESCRIPTION("Realtek 802.11ac wireless 8821cu driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821cu.h b/drivers/net/wireless/realtek/rtw88/rtw8821cu.h
new file mode 100644
index 0000000000000..c896792240011
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtw88/rtw8821cu.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/* Copyright(c) 2018-2019 Realtek Corporation
+ */
+
+#ifndef __RTW_8821CU_H_
+#define __RTW_8821CU_H_
+
+extern struct rtw_chip_info rtw8821c_hw_spec;
+
+#endif
--
2.30.2

2022-11-22 14:58:49

by Sascha Hauer

[permalink] [raw]
Subject: Re: [PATCH v3 00/11] RTW88: Add support for USB variants

On Tue, Nov 22, 2022 at 03:52:15PM +0100, Sascha Hauer wrote:
> This is the third round of adding support for the USB variants to the
> RTW88 driver. There are a few changes to the last version which make it
> worth looking at this version.
>
> First of all RTL8723du and RTL8821cu are tested working now. The issue
> here was that the txdesc checksum calculation was wrong. I found the
> correct calculation in various downstream drivers found on github.
>
> The second big issue was that TX packet aggregation was wrong. When
> aggregating packets each packet start has to be aligned to eight bytes.
> The necessary alignment was added to the total URB length before
> checking if there is another packet to aggregate, so the URB length
> included that padding after the last packet, which is wrong. Fixing
> this makes the driver work much more reliably.
>
> I added all people to Cc: who showed interest in this driver and I want
> to welcome you for testing and reviewing.

There still is a problem with the RTL8822cu chipset I have here. When
using NetworkManager I immediately lose the connection to the AP after
it has been connected:

[ 376.213846] wlan0: authenticate with 76:83:c2:ce:81:b1
[ 380.085463] wlan0: send auth to 76:83:c2:ce:81:b1 (try 1/3)
[ 380.091446] wlan0: authenticated
[ 380.108864] wlan0: associate with 76:83:c2:ce:81:b1 (try 1/3)
[ 380.136448] wlan0: RX AssocResp from 76:83:c2:ce:81:b1 (capab=0x1411 status=0 aid=2)
[ 380.202955] wlan0: associated
[ 380.268140] IPv6: ADDRCONF(NETDEV_CHANGE): wlan0: link becomes ready
[ 380.275328] wlan0: Connection to AP 76:83:c2:ce:81:b1 lost

That doesn't happen when using plain wpa_supplicant. This seems to go
down to cd96e22bc1da ("rtw88: add beacon filter support"). After being
connected I get a BCN_FILTER_CONNECTION_LOSS beacon. Plain
wpa_supplicant seems to go another code patch and doesn't activate
connection quality monitoring.

The connection to the AP works fluently also with NetworkManager though
when I just ignore the BCN_FILTER_CONNECTION_LOSS beacon.

Any idea what may be wrong here?

Sascha

--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |

2022-11-24 06:53:52

by Ping-Ke Shih

[permalink] [raw]
Subject: RE: [PATCH v3 00/11] RTW88: Add support for USB variants


> -----Original Message-----
> From: Sascha Hauer <[email protected]>
> Sent: Tuesday, November 22, 2022 10:55 PM
> To: Bernie Huang <[email protected]>
> Cc: [email protected]; Ping-Ke Shih <[email protected]>; Hans Ulli Kroll
> <[email protected]>; Martin Blumenstingl <[email protected]>; [email protected];
> Kalle Valo <[email protected]>; Yan-Hsuan Chuang <[email protected]>; [email protected];
> Viktor Petrenko <[email protected]>; Neo Jou <[email protected]>; Bernie Huang <[email protected]>;
> [email protected]; Johannes Berg <[email protected]>; Alexander Hochbaum <[email protected]>;
> Da Xue <[email protected]>
> Subject: Re: [PATCH v3 00/11] RTW88: Add support for USB variants
>
> On Tue, Nov 22, 2022 at 03:52:15PM +0100, Sascha Hauer wrote:
> > This is the third round of adding support for the USB variants to the
> > RTW88 driver. There are a few changes to the last version which make it
> > worth looking at this version.
> >
> > First of all RTL8723du and RTL8821cu are tested working now. The issue
> > here was that the txdesc checksum calculation was wrong. I found the
> > correct calculation in various downstream drivers found on github.
> >
> > The second big issue was that TX packet aggregation was wrong. When
> > aggregating packets each packet start has to be aligned to eight bytes.
> > The necessary alignment was added to the total URB length before
> > checking if there is another packet to aggregate, so the URB length
> > included that padding after the last packet, which is wrong. Fixing
> > this makes the driver work much more reliably.
> >
> > I added all people to Cc: who showed interest in this driver and I want
> > to welcome you for testing and reviewing.
>
> There still is a problem with the RTL8822cu chipset I have here. When
> using NetworkManager I immediately lose the connection to the AP after
> it has been connected:
>
> [ 376.213846] wlan0: authenticate with 76:83:c2:ce:81:b1
> [ 380.085463] wlan0: send auth to 76:83:c2:ce:81:b1 (try 1/3)
> [ 380.091446] wlan0: authenticated
> [ 380.108864] wlan0: associate with 76:83:c2:ce:81:b1 (try 1/3)
> [ 380.136448] wlan0: RX AssocResp from 76:83:c2:ce:81:b1 (capab=0x1411 status=0 aid=2)
> [ 380.202955] wlan0: associated
> [ 380.268140] IPv6: ADDRCONF(NETDEV_CHANGE): wlan0: link becomes ready
> [ 380.275328] wlan0: Connection to AP 76:83:c2:ce:81:b1 lost
>
> That doesn't happen when using plain wpa_supplicant. This seems to go
> down to cd96e22bc1da ("rtw88: add beacon filter support"). After being
> connected I get a BCN_FILTER_CONNECTION_LOSS beacon. Plain
> wpa_supplicant seems to go another code patch and doesn't activate
> connection quality monitoring.
>
> The connection to the AP works fluently also with NetworkManager though
> when I just ignore the BCN_FILTER_CONNECTION_LOSS beacon.
>
> Any idea what may be wrong here?
>

Please reference to below patch to see if it can work to you.

https://lore.kernel.org/linux-wireless/[email protected]/T/#u

Ping-Ke

2022-11-24 08:32:39

by Sascha Hauer

[permalink] [raw]
Subject: Re: [PATCH v3 00/11] RTW88: Add support for USB variants

On Thu, Nov 24, 2022 at 06:48:23AM +0000, Ping-Ke Shih wrote:
>
> > -----Original Message-----
> > From: Sascha Hauer <[email protected]>
> > Sent: Tuesday, November 22, 2022 10:55 PM
> > To: Bernie Huang <[email protected]>
> > Cc: [email protected]; Ping-Ke Shih <[email protected]>; Hans Ulli Kroll
> > <[email protected]>; Martin Blumenstingl <[email protected]>; [email protected];
> > Kalle Valo <[email protected]>; Yan-Hsuan Chuang <[email protected]>; [email protected];
> > Viktor Petrenko <[email protected]>; Neo Jou <[email protected]>; Bernie Huang <[email protected]>;
> > [email protected]; Johannes Berg <[email protected]>; Alexander Hochbaum <[email protected]>;
> > Da Xue <[email protected]>
> > Subject: Re: [PATCH v3 00/11] RTW88: Add support for USB variants
> >
> > On Tue, Nov 22, 2022 at 03:52:15PM +0100, Sascha Hauer wrote:
> > > This is the third round of adding support for the USB variants to the
> > > RTW88 driver. There are a few changes to the last version which make it
> > > worth looking at this version.
> > >
> > > First of all RTL8723du and RTL8821cu are tested working now. The issue
> > > here was that the txdesc checksum calculation was wrong. I found the
> > > correct calculation in various downstream drivers found on github.
> > >
> > > The second big issue was that TX packet aggregation was wrong. When
> > > aggregating packets each packet start has to be aligned to eight bytes.
> > > The necessary alignment was added to the total URB length before
> > > checking if there is another packet to aggregate, so the URB length
> > > included that padding after the last packet, which is wrong. Fixing
> > > this makes the driver work much more reliably.
> > >
> > > I added all people to Cc: who showed interest in this driver and I want
> > > to welcome you for testing and reviewing.
> >
> > There still is a problem with the RTL8822cu chipset I have here. When
> > using NetworkManager I immediately lose the connection to the AP after
> > it has been connected:
> >
> > [ 376.213846] wlan0: authenticate with 76:83:c2:ce:81:b1
> > [ 380.085463] wlan0: send auth to 76:83:c2:ce:81:b1 (try 1/3)
> > [ 380.091446] wlan0: authenticated
> > [ 380.108864] wlan0: associate with 76:83:c2:ce:81:b1 (try 1/3)
> > [ 380.136448] wlan0: RX AssocResp from 76:83:c2:ce:81:b1 (capab=0x1411 status=0 aid=2)
> > [ 380.202955] wlan0: associated
> > [ 380.268140] IPv6: ADDRCONF(NETDEV_CHANGE): wlan0: link becomes ready
> > [ 380.275328] wlan0: Connection to AP 76:83:c2:ce:81:b1 lost
> >
> > That doesn't happen when using plain wpa_supplicant. This seems to go
> > down to cd96e22bc1da ("rtw88: add beacon filter support"). After being
> > connected I get a BCN_FILTER_CONNECTION_LOSS beacon. Plain
> > wpa_supplicant seems to go another code patch and doesn't activate
> > connection quality monitoring.
> >
> > The connection to the AP works fluently also with NetworkManager though
> > when I just ignore the BCN_FILTER_CONNECTION_LOSS beacon.
> >
> > Any idea what may be wrong here?
> >
>
> Please reference to below patch to see if it can work to you.
>
> https://lore.kernel.org/linux-wireless/[email protected]/T/#u

Great! That solves this issue \o/

Sascha

--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |

2022-11-24 08:34:22

by Ping-Ke Shih

[permalink] [raw]
Subject: RE: [PATCH v3 00/11] RTW88: Add support for USB variants



> -----Original Message-----
> From: Sascha Hauer <[email protected]>
> Sent: Thursday, November 24, 2022 4:22 PM
> To: Ping-Ke Shih <[email protected]>
> Cc: Bernie Huang <[email protected]>; [email protected]; Hans Ulli Kroll
> <[email protected]>; Martin Blumenstingl <[email protected]>; [email protected];
> Kalle Valo <[email protected]>; Yan-Hsuan Chuang <[email protected]>; [email protected];
> Viktor Petrenko <[email protected]>; Neo Jou <[email protected]>; [email protected]; Johannes Berg
> <[email protected]>; Alexander Hochbaum <[email protected]>; Da Xue <[email protected]>
> Subject: Re: [PATCH v3 00/11] RTW88: Add support for USB variants
>
> On Thu, Nov 24, 2022 at 06:48:23AM +0000, Ping-Ke Shih wrote:
> >
> > > -----Original Message-----
> > > From: Sascha Hauer <[email protected]>
> > > Sent: Tuesday, November 22, 2022 10:55 PM
> > > To: Bernie Huang <[email protected]>
> > > Cc: [email protected]; Ping-Ke Shih <[email protected]>; Hans Ulli Kroll
> > > <[email protected]>; Martin Blumenstingl <[email protected]>;
> [email protected];
> > > Kalle Valo <[email protected]>; Yan-Hsuan Chuang <[email protected]>;
> [email protected];
> > > Viktor Petrenko <[email protected]>; Neo Jou <[email protected]>; Bernie Huang <[email protected]>;
> > > [email protected]; Johannes Berg <[email protected]>; Alexander Hochbaum
> <[email protected]>;
> > > Da Xue <[email protected]>
> > > Subject: Re: [PATCH v3 00/11] RTW88: Add support for USB variants
> > >
> > > On Tue, Nov 22, 2022 at 03:52:15PM +0100, Sascha Hauer wrote:
> > > > This is the third round of adding support for the USB variants to the
> > > > RTW88 driver. There are a few changes to the last version which make it
> > > > worth looking at this version.
> > > >
> > > > First of all RTL8723du and RTL8821cu are tested working now. The issue
> > > > here was that the txdesc checksum calculation was wrong. I found the
> > > > correct calculation in various downstream drivers found on github.
> > > >
> > > > The second big issue was that TX packet aggregation was wrong. When
> > > > aggregating packets each packet start has to be aligned to eight bytes.
> > > > The necessary alignment was added to the total URB length before
> > > > checking if there is another packet to aggregate, so the URB length
> > > > included that padding after the last packet, which is wrong. Fixing
> > > > this makes the driver work much more reliably.
> > > >
> > > > I added all people to Cc: who showed interest in this driver and I want
> > > > to welcome you for testing and reviewing.
> > >
> > > There still is a problem with the RTL8822cu chipset I have here. When
> > > using NetworkManager I immediately lose the connection to the AP after
> > > it has been connected:
> > >
> > > [ 376.213846] wlan0: authenticate with 76:83:c2:ce:81:b1
> > > [ 380.085463] wlan0: send auth to 76:83:c2:ce:81:b1 (try 1/3)
> > > [ 380.091446] wlan0: authenticated
> > > [ 380.108864] wlan0: associate with 76:83:c2:ce:81:b1 (try 1/3)
> > > [ 380.136448] wlan0: RX AssocResp from 76:83:c2:ce:81:b1 (capab=0x1411 status=0 aid=2)
> > > [ 380.202955] wlan0: associated
> > > [ 380.268140] IPv6: ADDRCONF(NETDEV_CHANGE): wlan0: link becomes ready
> > > [ 380.275328] wlan0: Connection to AP 76:83:c2:ce:81:b1 lost
> > >
> > > That doesn't happen when using plain wpa_supplicant. This seems to go
> > > down to cd96e22bc1da ("rtw88: add beacon filter support"). After being
> > > connected I get a BCN_FILTER_CONNECTION_LOSS beacon. Plain
> > > wpa_supplicant seems to go another code patch and doesn't activate
> > > connection quality monitoring.
> > >
> > > The connection to the AP works fluently also with NetworkManager though
> > > when I just ignore the BCN_FILTER_CONNECTION_LOSS beacon.
> > >
> > > Any idea what may be wrong here?
> > >
> >
> > Please reference to below patch to see if it can work to you.
> >
> > https://lore.kernel.org/linux-wireless/[email protected]/T/#u
>
> Great! That solves this issue \o/
>

Do you mind to add "Tested-by:" tag to the patch? :-)

Ping-Ke


2022-11-24 08:36:25

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH v3 00/11] RTW88: Add support for USB variants

Sascha Hauer <[email protected]> writes:

>> > There still is a problem with the RTL8822cu chipset I have here. When
>> > using NetworkManager I immediately lose the connection to the AP after
>> > it has been connected:
>> >
>> > [ 376.213846] wlan0: authenticate with 76:83:c2:ce:81:b1
>> > [ 380.085463] wlan0: send auth to 76:83:c2:ce:81:b1 (try 1/3)
>> > [ 380.091446] wlan0: authenticated
>> > [ 380.108864] wlan0: associate with 76:83:c2:ce:81:b1 (try 1/3)
>> > [ 380.136448] wlan0: RX AssocResp from 76:83:c2:ce:81:b1
>> > (capab=0x1411 status=0 aid=2)
>> > [ 380.202955] wlan0: associated
>> > [ 380.268140] IPv6: ADDRCONF(NETDEV_CHANGE): wlan0: link becomes ready
>> > [ 380.275328] wlan0: Connection to AP 76:83:c2:ce:81:b1 lost
>> >
>> > That doesn't happen when using plain wpa_supplicant. This seems to go
>> > down to cd96e22bc1da ("rtw88: add beacon filter support"). After being
>> > connected I get a BCN_FILTER_CONNECTION_LOSS beacon. Plain
>> > wpa_supplicant seems to go another code patch and doesn't activate
>> > connection quality monitoring.
>> >
>> > The connection to the AP works fluently also with NetworkManager though
>> > when I just ignore the BCN_FILTER_CONNECTION_LOSS beacon.
>> >
>> > Any idea what may be wrong here?
>> >
>>
>> Please reference to below patch to see if it can work to you.
>>
>> https://lore.kernel.org/linux-wireless/[email protected]/T/#u
>
> Great! That solves this issue \o/

Awesome, great work Ping and Ji-Pin!

--
https://patchwork.kernel.org/project/linux-wireless/list/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches

2022-11-24 08:38:29

by Sascha Hauer

[permalink] [raw]
Subject: Re: [PATCH v3 00/11] RTW88: Add support for USB variants

On Thu, Nov 24, 2022 at 08:26:23AM +0000, Ping-Ke Shih wrote:
>
>
> > -----Original Message-----
> > From: Sascha Hauer <[email protected]>
> > Sent: Thursday, November 24, 2022 4:22 PM
> > To: Ping-Ke Shih <[email protected]>
> > Cc: Bernie Huang <[email protected]>; [email protected]; Hans Ulli Kroll
> > <[email protected]>; Martin Blumenstingl <[email protected]>; [email protected];
> > Kalle Valo <[email protected]>; Yan-Hsuan Chuang <[email protected]>; [email protected];
> > Viktor Petrenko <[email protected]>; Neo Jou <[email protected]>; [email protected]; Johannes Berg
> > <[email protected]>; Alexander Hochbaum <[email protected]>; Da Xue <[email protected]>
> > Subject: Re: [PATCH v3 00/11] RTW88: Add support for USB variants
> >
> > On Thu, Nov 24, 2022 at 06:48:23AM +0000, Ping-Ke Shih wrote:
> > >
> > > > -----Original Message-----
> > > > From: Sascha Hauer <[email protected]>
> > > > Sent: Tuesday, November 22, 2022 10:55 PM
> > > > To: Bernie Huang <[email protected]>
> > > > Cc: [email protected]; Ping-Ke Shih <[email protected]>; Hans Ulli Kroll
> > > > <[email protected]>; Martin Blumenstingl <[email protected]>;
> > [email protected];
> > > > Kalle Valo <[email protected]>; Yan-Hsuan Chuang <[email protected]>;
> > [email protected];
> > > > Viktor Petrenko <[email protected]>; Neo Jou <[email protected]>; Bernie Huang <[email protected]>;
> > > > [email protected]; Johannes Berg <[email protected]>; Alexander Hochbaum
> > <[email protected]>;
> > > > Da Xue <[email protected]>
> > > > Subject: Re: [PATCH v3 00/11] RTW88: Add support for USB variants
> > > >
> > > > On Tue, Nov 22, 2022 at 03:52:15PM +0100, Sascha Hauer wrote:
> > > > > This is the third round of adding support for the USB variants to the
> > > > > RTW88 driver. There are a few changes to the last version which make it
> > > > > worth looking at this version.
> > > > >
> > > > > First of all RTL8723du and RTL8821cu are tested working now. The issue
> > > > > here was that the txdesc checksum calculation was wrong. I found the
> > > > > correct calculation in various downstream drivers found on github.
> > > > >
> > > > > The second big issue was that TX packet aggregation was wrong. When
> > > > > aggregating packets each packet start has to be aligned to eight bytes.
> > > > > The necessary alignment was added to the total URB length before
> > > > > checking if there is another packet to aggregate, so the URB length
> > > > > included that padding after the last packet, which is wrong. Fixing
> > > > > this makes the driver work much more reliably.
> > > > >
> > > > > I added all people to Cc: who showed interest in this driver and I want
> > > > > to welcome you for testing and reviewing.
> > > >
> > > > There still is a problem with the RTL8822cu chipset I have here. When
> > > > using NetworkManager I immediately lose the connection to the AP after
> > > > it has been connected:
> > > >
> > > > [ 376.213846] wlan0: authenticate with 76:83:c2:ce:81:b1
> > > > [ 380.085463] wlan0: send auth to 76:83:c2:ce:81:b1 (try 1/3)
> > > > [ 380.091446] wlan0: authenticated
> > > > [ 380.108864] wlan0: associate with 76:83:c2:ce:81:b1 (try 1/3)
> > > > [ 380.136448] wlan0: RX AssocResp from 76:83:c2:ce:81:b1 (capab=0x1411 status=0 aid=2)
> > > > [ 380.202955] wlan0: associated
> > > > [ 380.268140] IPv6: ADDRCONF(NETDEV_CHANGE): wlan0: link becomes ready
> > > > [ 380.275328] wlan0: Connection to AP 76:83:c2:ce:81:b1 lost
> > > >
> > > > That doesn't happen when using plain wpa_supplicant. This seems to go
> > > > down to cd96e22bc1da ("rtw88: add beacon filter support"). After being
> > > > connected I get a BCN_FILTER_CONNECTION_LOSS beacon. Plain
> > > > wpa_supplicant seems to go another code patch and doesn't activate
> > > > connection quality monitoring.
> > > >
> > > > The connection to the AP works fluently also with NetworkManager though
> > > > when I just ignore the BCN_FILTER_CONNECTION_LOSS beacon.
> > > >
> > > > Any idea what may be wrong here?
> > > >
> > >
> > > Please reference to below patch to see if it can work to you.
> > >
> > > https://lore.kernel.org/linux-wireless/[email protected]/T/#u
> >
> > Great! That solves this issue \o/
> >
>
> Do you mind to add "Tested-by:" tag to the patch? :-)

You should already find it in your inbox. Thank you very much for the
fast response :)

Sascha

--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |

2022-11-24 09:21:57

by Sascha Hauer

[permalink] [raw]
Subject: Re: [PATCH v3 00/11] RTW88: Add support for USB variants

On Thu, Nov 24, 2022 at 09:21:58AM +0100, Sascha Hauer wrote:
> On Thu, Nov 24, 2022 at 06:48:23AM +0000, Ping-Ke Shih wrote:
> >
> > > -----Original Message-----
> > > From: Sascha Hauer <[email protected]>
> > > Sent: Tuesday, November 22, 2022 10:55 PM
> > > To: Bernie Huang <[email protected]>
> > > Cc: [email protected]; Ping-Ke Shih <[email protected]>; Hans Ulli Kroll
> > > <[email protected]>; Martin Blumenstingl <[email protected]>; [email protected];
> > > Kalle Valo <[email protected]>; Yan-Hsuan Chuang <[email protected]>; [email protected];
> > > Viktor Petrenko <[email protected]>; Neo Jou <[email protected]>; Bernie Huang <[email protected]>;
> > > [email protected]; Johannes Berg <[email protected]>; Alexander Hochbaum <[email protected]>;
> > > Da Xue <[email protected]>
> > > Subject: Re: [PATCH v3 00/11] RTW88: Add support for USB variants
> > >
> > > On Tue, Nov 22, 2022 at 03:52:15PM +0100, Sascha Hauer wrote:
> > > > This is the third round of adding support for the USB variants to the
> > > > RTW88 driver. There are a few changes to the last version which make it
> > > > worth looking at this version.
> > > >
> > > > First of all RTL8723du and RTL8821cu are tested working now. The issue
> > > > here was that the txdesc checksum calculation was wrong. I found the
> > > > correct calculation in various downstream drivers found on github.
> > > >
> > > > The second big issue was that TX packet aggregation was wrong. When
> > > > aggregating packets each packet start has to be aligned to eight bytes.
> > > > The necessary alignment was added to the total URB length before
> > > > checking if there is another packet to aggregate, so the URB length
> > > > included that padding after the last packet, which is wrong. Fixing
> > > > this makes the driver work much more reliably.
> > > >
> > > > I added all people to Cc: who showed interest in this driver and I want
> > > > to welcome you for testing and reviewing.
> > >
> > > There still is a problem with the RTL8822cu chipset I have here. When
> > > using NetworkManager I immediately lose the connection to the AP after
> > > it has been connected:
> > >
> > > [ 376.213846] wlan0: authenticate with 76:83:c2:ce:81:b1
> > > [ 380.085463] wlan0: send auth to 76:83:c2:ce:81:b1 (try 1/3)
> > > [ 380.091446] wlan0: authenticated
> > > [ 380.108864] wlan0: associate with 76:83:c2:ce:81:b1 (try 1/3)
> > > [ 380.136448] wlan0: RX AssocResp from 76:83:c2:ce:81:b1 (capab=0x1411 status=0 aid=2)
> > > [ 380.202955] wlan0: associated
> > > [ 380.268140] IPv6: ADDRCONF(NETDEV_CHANGE): wlan0: link becomes ready
> > > [ 380.275328] wlan0: Connection to AP 76:83:c2:ce:81:b1 lost
> > >
> > > That doesn't happen when using plain wpa_supplicant. This seems to go
> > > down to cd96e22bc1da ("rtw88: add beacon filter support"). After being
> > > connected I get a BCN_FILTER_CONNECTION_LOSS beacon. Plain
> > > wpa_supplicant seems to go another code patch and doesn't activate
> > > connection quality monitoring.
> > >
> > > The connection to the AP works fluently also with NetworkManager though
> > > when I just ignore the BCN_FILTER_CONNECTION_LOSS beacon.
> > >
> > > Any idea what may be wrong here?
> > >
> >
> > Please reference to below patch to see if it can work to you.
> >
> > https://lore.kernel.org/linux-wireless/[email protected]/T/#u
>
> Great! That solves this issue \o/

I am also happy to say that this patch is a real performance boost.
Here are some numbers:

RTL8723DU, no patch
===================
tx [ 5] 0.00-10.00 sec 1.08 MBytes 903 Kbits/sec 1 sender
rx [ 5] 0.00-10.26 sec 10.3 MBytes 8.41 Mbits/sec 0 sender

RTL8723DU, with patch
=====================
tx [ 5] 0.00-10.00 sec 34.7 MBytes 29.1 Mbits/sec 9 sender
rx [ 5] 0.00-10.05 sec 34.4 MBytes 28.7 Mbits/sec 5 sender

RTL8821CU, no patch
===================
tx [ 5] 0.00-10.00 sec 6.01 MBytes 5.04 Mbits/sec 0 sender
rx [ 5] 0.00-10.44 sec 53.4 MBytes 42.9 Mbits/sec 0 sender

RTL8821CU, with patch
===================
tx [ 5] 0.00-10.00 sec 57.9 MBytes 48.6 Mbits/sec 0 sender
rx [ 5] 0.00-10.15 sec 66.3 MBytes 54.8 Mbits/sec 419 sender

RTL8822CU, no patch
===================
tx [ 5] 0.00-10.00 sec 11.8 MBytes 9.91 Mbits/sec 1 sender
rx [ 5] 0.00-10.18 sec 105 MBytes 86.3 Mbits/sec 805 sender

RTL8822CU, with patch
===================
tx [ 5] 0.00-10.01 sec 80.0 MBytes 67.1 Mbits/sec 0 sender
rx [ 5] 0.00-10.12 sec 117 MBytes 97.2 Mbits/sec 658 sender

Tested with:

tx: iperf3 -c 192.168.0.57 -i0
rx: iperf3 -c 192.168.0.57 -i0 -R

Especially the RTL8723DU now starts being useful.

Sascha

--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |

2022-11-25 08:30:26

by Ping-Ke Shih

[permalink] [raw]
Subject: RE: [PATCH v3 02/11] rtw88: Call rtw_fw_beacon_filter_config() with rtwdev->mutex held


> -----Original Message-----
> From: Sascha Hauer <[email protected]>
> Sent: Tuesday, November 22, 2022 10:52 PM
> To: [email protected]
> Cc: Neo Jou <[email protected]>; Hans Ulli Kroll <[email protected]>; Ping-Ke Shih <[email protected]>;
> Yan-Hsuan Chuang <[email protected]>; Kalle Valo <[email protected]>; [email protected];
> [email protected]; Martin Blumenstingl <[email protected]>;
> [email protected]; Johannes Berg <[email protected]>; Alexander Hochbaum <[email protected]>;
> Da Xue <[email protected]>; Bernie Huang <[email protected]>; Viktor Petrenko <[email protected]>;
> Sascha Hauer <[email protected]>
> Subject: [PATCH v3 02/11] rtw88: Call rtw_fw_beacon_filter_config() with rtwdev->mutex held
>
> rtw_fw_beacon_filter_config() is called once with rtwdev->mutex held
> and once without the mutex held. Call it consistently with rtwdev->mutex
> held.
>
> Signed-off-by: Sascha Hauer <[email protected]>

Reviewed-by: Ping-Ke Shih <[email protected]>

[...]


2022-11-28 02:08:19

by Ping-Ke Shih

[permalink] [raw]
Subject: RE: [PATCH v3 07/11] rtw88: Add common USB chip support



> -----Original Message-----
> From: Sascha Hauer <[email protected]>
> Sent: Tuesday, November 22, 2022 10:52 PM
> To: [email protected]
> Cc: Neo Jou <[email protected]>; Hans Ulli Kroll <[email protected]>; Ping-Ke Shih <[email protected]>;
> Yan-Hsuan Chuang <[email protected]>; Kalle Valo <[email protected]>; [email protected];
> [email protected]; Martin Blumenstingl <[email protected]>;
> [email protected]; Johannes Berg <[email protected]>; Alexander Hochbaum <[email protected]>;
> Da Xue <[email protected]>; Bernie Huang <[email protected]>; Viktor Petrenko <[email protected]>;
> Sascha Hauer <[email protected]>; neo_jou <[email protected]>
> Subject: [PATCH v3 07/11] rtw88: Add common USB chip support
>
> Add the common bits and pieces to add USB support to the RTW88 driver.
> This is based on https://github.com/ulli-kroll/rtw88-usb.git which
> itself is first written by Neo Jou.
>
> Signed-off-by: neo_jou <[email protected]>
> Signed-off-by: Hans Ulli Kroll <[email protected]>
> Signed-off-by: Sascha Hauer <[email protected]>
> ---
>
> Notes:
> Changes since v2:
> - Fix buffer length for aggregated tx packets
> - Increase maximum transmit buffer size to 20KiB as found in downstream drivers
> - Change register write functions to synchronous accesses instead of just firing
> a URB without waiting for its completion
> - requeue rx URBs directly in completion handler rather than having a workqueue
> for it.
>
> Changes since v1:
> - Make checkpatch.pl clean
> - Drop WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL flag
> - Use 'ret' as variable name for return values
> - Sort variable declarations in reverse Xmas tree order
> - Change potentially endless loop to a limited loop
> - Change locking to be more obviously correct
> - drop unnecessary check for !rtwdev
> - make sure the refill workqueue is not restarted again after we have
> cancelled it
>
> drivers/net/wireless/realtek/rtw88/Kconfig | 3 +
> drivers/net/wireless/realtek/rtw88/Makefile | 2 +
> drivers/net/wireless/realtek/rtw88/mac.c | 3 +
> drivers/net/wireless/realtek/rtw88/main.c | 4 +
> drivers/net/wireless/realtek/rtw88/main.h | 4 +
> drivers/net/wireless/realtek/rtw88/reg.h | 1 +
> drivers/net/wireless/realtek/rtw88/tx.h | 31 +
> drivers/net/wireless/realtek/rtw88/usb.c | 918 ++++++++++++++++++++
> drivers/net/wireless/realtek/rtw88/usb.h | 107 +++
> 9 files changed, 1073 insertions(+)
> create mode 100644 drivers/net/wireless/realtek/rtw88/usb.c
> create mode 100644 drivers/net/wireless/realtek/rtw88/usb.h
>
> diff --git a/drivers/net/wireless/realtek/rtw88/Kconfig b/drivers/net/wireless/realtek/rtw88/Kconfig
> index e3d7cb6c12902..1624c5db69bac 100644
> --- a/drivers/net/wireless/realtek/rtw88/Kconfig
> +++ b/drivers/net/wireless/realtek/rtw88/Kconfig
> @@ -16,6 +16,9 @@ config RTW88_CORE
> config RTW88_PCI
> tristate
>
> +config RTW88_USB
> + tristate
> +
> config RTW88_8822B
> tristate
>
> diff --git a/drivers/net/wireless/realtek/rtw88/Makefile b/drivers/net/wireless/realtek/rtw88/Makefile
> index 834c66ec0af9e..9e095f8181483 100644
> --- a/drivers/net/wireless/realtek/rtw88/Makefile
> +++ b/drivers/net/wireless/realtek/rtw88/Makefile
> @@ -45,4 +45,6 @@ obj-$(CONFIG_RTW88_8821CE) += rtw88_8821ce.o
> rtw88_8821ce-objs := rtw8821ce.o
>
> obj-$(CONFIG_RTW88_PCI) += rtw88_pci.o
> +obj-$(CONFIG_RTW88_USB) += rtw88_usb.o
> rtw88_pci-objs := pci.o
> +rtw88_usb-objs := usb.o

nit: I prefer not interleaving with PCI.


[...]

> diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c
> new file mode 100644
> index 0000000000000..4a12934d20712
> --- /dev/null
> +++ b/drivers/net/wireless/realtek/rtw88/usb.c

[...]

> +static u32 rtw_usb_read(struct rtw_dev *rtwdev, u32 addr, u16 len)
> +{
> + struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
> + struct usb_device *udev = rtwusb->udev;
> + __le32 *data;
> + unsigned long flags;
> + int ret;
> + static int count;
> +
> + spin_lock_irqsave(&rtwusb->usb_lock, flags);
> +
> + rtwusb->usb_data_index++;
> + rtwusb->usb_data_index &= (RTW_USB_MAX_RXTX_COUNT - 1);
> +
> + spin_unlock_irqrestore(&rtwusb->usb_lock, flags);
> +
> + data = &rtwusb->usb_data[rtwusb->usb_data_index];

Don't you need to hold &rtwusb->usb_lock to access rtwusb->usb_data_index?
rtw_usb_write() has similar code.

> +
> + ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
> + RTW_USB_CMD_REQ, RTW_USB_CMD_READ, addr,
> + RTW_USB_VENQT_CMD_IDX, data, len, 1000);
> + if (ret < 0 && ret != -ENODEV && count++ < 4)
> + rtw_err(rtwdev, "read register 0x%x failed with %d\n",
> + addr, ret);
> +
> + return le32_to_cpu(*data);
> +}
> +

[...]

> +
> +static void rtw_usb_write_port_tx_complete(struct urb *urb)
> +{
> + struct rtw_usb_txcb *txcb = urb->context;
> + struct rtw_dev *rtwdev = txcb->rtwdev;
> + struct ieee80211_hw *hw = rtwdev->hw;
> +
> + while (true) {

Is it possible to have a hard limit to prevent unexpected infinite loop?

> + struct sk_buff *skb = skb_dequeue(&txcb->tx_ack_queue);
> + struct ieee80211_tx_info *info;
> + struct rtw_usb_tx_data *tx_data;
> +
> + if (!skb)
> + break;
> +
> + info = IEEE80211_SKB_CB(skb);
> + tx_data = rtw_usb_get_tx_data(skb);
> +
> + /* enqueue to wait for tx report */
> + if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) {
> + rtw_tx_report_enqueue(rtwdev, skb, tx_data->sn);
> + continue;
> + }
> +
> + /* always ACK for others, then they won't be marked as drop */
> + ieee80211_tx_info_clear_status(info);
> + 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(hw, skb);
> + }
> +
> + kfree(txcb);
> +}
> +

[...]

> +
> +static bool rtw_usb_tx_agg_skb(struct rtw_usb *rtwusb, struct sk_buff_head *list)
> +{
> + struct rtw_dev *rtwdev = rtwusb->rtwdev;
> + struct rtw_usb_txcb *txcb;
> + struct sk_buff *skb_head;
> + struct sk_buff *skb_iter;
> + u8 *data_ptr;
> + int agg_num = 0;
> + unsigned int align_next = 0;
> +
> + if (skb_queue_empty(list))
> + return false;
> +
> + txcb = kmalloc(sizeof(*txcb), GFP_ATOMIC);
> + if (!txcb)
> + return false;
> +
> + txcb->rtwdev = rtwdev;
> + skb_queue_head_init(&txcb->tx_ack_queue);
> +
> + skb_iter = skb_dequeue(list);
> +
> + if (skb_queue_empty(list)) {
> + skb_head = skb_iter;
> + goto queue;
> + }
> +
> + skb_head = dev_alloc_skb(RTW_USB_MAX_XMITBUF_SZ);
> + if (!skb_head) {
> + skb_head = skb_iter;
> + goto queue;
> + }
> +
> + data_ptr = skb_head->data;
> +
> + while (skb_iter) {
> + unsigned long flags;
> +
> + memcpy(data_ptr, skb_iter->data, skb_iter->len);
> + skb_put(skb_head, skb_iter->len + align_next);

skb_put(skb_head, align_next);
skb_put_data(skb_head, skb_iter->data, skb_iter->len);

Then, don't need to maintain 'data_ptr'.

> +
> + align_next = ALIGN(skb_iter->len, 8) - skb_iter->len;
> + data_ptr += skb_iter->len + align_next;
> +
> + agg_num++;
> +
> + skb_queue_tail(&txcb->tx_ack_queue, skb_iter);
> +
> + spin_lock_irqsave(&list->lock, flags);
> +
> + skb_iter = skb_peek(list);
> +
> + if (skb_iter && skb_iter->len + skb_head->len <= RTW_USB_MAX_XMITBUF_SZ)
> + __skb_unlink(skb_iter, list);
> + else
> + skb_iter = NULL;
> + spin_unlock_irqrestore(&list->lock, flags);
> + }
> +
> + if (agg_num > 1)
> + rtw_usb_fill_tx_checksum(rtwusb, skb_head, agg_num);
> +
> +queue:
> + skb_queue_tail(&txcb->tx_ack_queue, skb_head);
> +
> + rtw_usb_write_port(rtwdev, GET_TX_DESC_QSEL(skb_head->data), skb_head,
> + rtw_usb_write_port_tx_complete, txcb);
> +
> + return true;
> +}
> +

[...]

> +
> +static void rtw_usb_rx_resubmit(struct rtw_usb *rtwusb, struct rx_usb_ctrl_block *rxcb)
> +{
> + struct rtw_dev *rtwdev = rtwusb->rtwdev;
> + int error;
> +
> + rxcb->rx_skb = alloc_skb(RTW_USB_MAX_RECVBUF_SZ, GFP_ATOMIC);
> + if (!rxcb->rx_skb)
> + return;
> +
> + usb_fill_bulk_urb(rxcb->rx_urb, rtwusb->udev,
> + usb_rcvbulkpipe(rtwusb->udev, rtwusb->pipe_in),
> + rxcb->rx_skb->data, RTW_USB_MAX_RECVBUF_SZ,
> + rtw_usb_read_port_complete, rxcb);
> +
> + error = usb_submit_urb(rxcb->rx_urb, GFP_ATOMIC);
> + if (error) {
> + kfree_skb(rxcb->rx_skb);
> + if (error != -ENODEV)
> + rtw_err(rtwdev, "Err sending rx data urb %d\n",
> + error);

nit: straighten rtw_err()

> + }
> +}
> +

[...]

> diff --git a/drivers/net/wireless/realtek/rtw88/usb.h b/drivers/net/wireless/realtek/rtw88/usb.h
> new file mode 100644
> index 0000000000000..e26f8afb09f29
> --- /dev/null
> +++ b/drivers/net/wireless/realtek/rtw88/usb.h

[...]

> +
> +static inline struct rtw_usb_tx_data *rtw_usb_get_tx_data(struct sk_buff *skb)
> +{
> + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
> +
> + BUILD_BUG_ON(sizeof(struct rtw_usb_tx_data) >
> + sizeof(info->status.status_driver_data));

coding style:

align the open parenthesis

BUILD_BUG_ON(sizeof(struct rtw_usb_tx_data) >
sizeof(info->status.status_driver_data));

> +
> + return (struct rtw_usb_tx_data *)info->status.status_driver_data;
> +}
> +
> +int rtw_usb_probe(struct usb_interface *intf, const struct usb_device_id *id);
> +void rtw_usb_disconnect(struct usb_interface *intf);
> +
> +#endif
> --
> 2.30.2

2022-11-28 02:41:47

by Ping-Ke Shih

[permalink] [raw]
Subject: RE: [PATCH v3 08/11] rtw88: Add rtw8821cu chipset support



> -----Original Message-----
> From: Sascha Hauer <[email protected]>
> Sent: Tuesday, November 22, 2022 10:52 PM
> To: [email protected]
> Cc: Neo Jou <[email protected]>; Hans Ulli Kroll <[email protected]>; Ping-Ke Shih <[email protected]>;
> Yan-Hsuan Chuang <[email protected]>; Kalle Valo <[email protected]>; [email protected];
> [email protected]; Martin Blumenstingl <[email protected]>;
> [email protected]; Johannes Berg <[email protected]>; Alexander Hochbaum <[email protected]>;
> Da Xue <[email protected]>; Bernie Huang <[email protected]>; Viktor Petrenko <[email protected]>;
> Sascha Hauer <[email protected]>
> Subject: [PATCH v3 08/11] rtw88: Add rtw8821cu chipset support
>
> Add support for the rtw8821cu chipset based on
> https://github.com/ulli-kroll/rtw88-usb.git
>
> Signed-off-by: Sascha Hauer <[email protected]>
> ---
>
> Notes:
> Changes since v2:
> - Fix txdesc checksum calculation. The checksum must be calculated over
> a fixed number of words.
>
> drivers/net/wireless/realtek/rtw88/Kconfig | 11 ++++
> drivers/net/wireless/realtek/rtw88/Makefile | 3 ++
> drivers/net/wireless/realtek/rtw88/rtw8821c.c | 18 +++++++
> drivers/net/wireless/realtek/rtw88/rtw8821c.h | 21 ++++++++
> .../net/wireless/realtek/rtw88/rtw8821cu.c | 50 +++++++++++++++++++
> .../net/wireless/realtek/rtw88/rtw8821cu.h | 10 ++++
> 6 files changed, 113 insertions(+)
> create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8821cu.c
> create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8821cu.h
>

[...]

> --- /dev/null
> +++ b/drivers/net/wireless/realtek/rtw88/rtw8821cu.h
> @@ -0,0 +1,10 @@
> +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
> +/* Copyright(c) 2018-2019 Realtek Corporation
> + */
> +
> +#ifndef __RTW_8821CU_H_
> +#define __RTW_8821CU_H_
> +
> +extern struct rtw_chip_info rtw8821c_hw_spec;

This has been moved to rtw8821c.h by
89d8f53ff6e ("wifi: rtw88: Fix Sparse warning for rtw8821c_hw_spec")

So, we don't need rtw8821cu.h anymore.
Please apply this rule to other chips.

> +
> +#endif
> --
> 2.30.2

2022-11-28 04:04:36

by Ping-Ke Shih

[permalink] [raw]
Subject: RE: [PATCH v3 00/11] RTW88: Add support for USB variants


> -----Original Message-----
> From: Sascha Hauer <[email protected]>
> Sent: Tuesday, November 22, 2022 10:52 PM
> To: [email protected]
> Cc: Neo Jou <[email protected]>; Hans Ulli Kroll <[email protected]>; Ping-Ke Shih <[email protected]>;
> Yan-Hsuan Chuang <[email protected]>; Kalle Valo <[email protected]>; [email protected];
> [email protected]; Martin Blumenstingl <[email protected]>;
> [email protected]; Johannes Berg <[email protected]>; Alexander Hochbaum <[email protected]>;
> Da Xue <[email protected]>; Bernie Huang <[email protected]>; Viktor Petrenko <[email protected]>;
> Sascha Hauer <[email protected]>
> Subject: [PATCH v3 00/11] RTW88: Add support for USB variants
>
> This is the third round of adding support for the USB variants to the
> RTW88 driver. There are a few changes to the last version which make it
> worth looking at this version.
>
> First of all RTL8723du and RTL8821cu are tested working now. The issue
> here was that the txdesc checksum calculation was wrong. I found the
> correct calculation in various downstream drivers found on github.
>
> The second big issue was that TX packet aggregation was wrong. When
> aggregating packets each packet start has to be aligned to eight bytes.
> The necessary alignment was added to the total URB length before
> checking if there is another packet to aggregate, so the URB length
> included that padding after the last packet, which is wrong. Fixing
> this makes the driver work much more reliably.
>

Thanks for your finding and fixes on this driver. I have reviewed this
patchset and written some comments. No big problem.


>
> Sascha Hauer (11):
> rtw88: print firmware type in info message
> rtw88: Call rtw_fw_beacon_filter_config() with rtwdev->mutex held
> rtw88: Drop rf_lock
> rtw88: Drop h2c.lock
> rtw88: Drop coex mutex
> rtw88: iterate over vif/sta list non-atomically
> rtw88: Add common USB chip support
> rtw88: Add rtw8821cu chipset support
> rtw88: Add rtw8822bu chipset support
> rtw88: Add rtw8822cu chipset support
> rtw88: Add rtw8723du chipset support

Please use "wifi: rtw88: " as prefix in next version.

--
Ping-Ke


2022-11-28 05:50:47

by Ryan Finnie

[permalink] [raw]
Subject: Re: [PATCH v3 09/11] rtw88: Add rtw8822bu chipset support

> + { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x012e, 0xff, 0xff, 0xff),
> + .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TP-LINK */

This device is confirmed in the wild as "TP-LINK Archer T3U Nano", and
is a miniaturized version of 0x012d.

(I have not personally tested this patchset, but have verified against
the DKMS tree at https://github.com/cilynx/rtl88x2bu with 0x012e added.)

Thank you,
Ryan Finnie

2022-11-28 10:34:18

by Sascha Hauer

[permalink] [raw]
Subject: Re: [PATCH v3 07/11] rtw88: Add common USB chip support

On Mon, Nov 28, 2022 at 02:00:54AM +0000, Ping-Ke Shih wrote:
>
>
> > -----Original Message-----
> > From: Sascha Hauer <[email protected]>
> > Sent: Tuesday, November 22, 2022 10:52 PM
> > To: [email protected]
> > Cc: Neo Jou <[email protected]>; Hans Ulli Kroll <[email protected]>; Ping-Ke Shih <[email protected]>;
> > Yan-Hsuan Chuang <[email protected]>; Kalle Valo <[email protected]>; [email protected];
> > [email protected]; Martin Blumenstingl <[email protected]>;
> > [email protected]; Johannes Berg <[email protected]>; Alexander Hochbaum <[email protected]>;
> > Da Xue <[email protected]>; Bernie Huang <[email protected]>; Viktor Petrenko <[email protected]>;
> > Sascha Hauer <[email protected]>; neo_jou <[email protected]>
> > Subject: [PATCH v3 07/11] rtw88: Add common USB chip support
> >
> > Add the common bits and pieces to add USB support to the RTW88 driver.
> > This is based on https://github.com/ulli-kroll/rtw88-usb.git which
> > itself is first written by Neo Jou.
> >
> > Signed-off-by: neo_jou <[email protected]>
> > Signed-off-by: Hans Ulli Kroll <[email protected]>
> > Signed-off-by: Sascha Hauer <[email protected]>
> > ---
> >
> > Notes:
> > Changes since v2:
> > - Fix buffer length for aggregated tx packets
> > - Increase maximum transmit buffer size to 20KiB as found in downstream drivers
> > - Change register write functions to synchronous accesses instead of just firing
> > a URB without waiting for its completion
> > - requeue rx URBs directly in completion handler rather than having a workqueue
> > for it.
> >
> > Changes since v1:
> > - Make checkpatch.pl clean
> > - Drop WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL flag
> > - Use 'ret' as variable name for return values
> > - Sort variable declarations in reverse Xmas tree order
> > - Change potentially endless loop to a limited loop
> > - Change locking to be more obviously correct
> > - drop unnecessary check for !rtwdev
> > - make sure the refill workqueue is not restarted again after we have
> > cancelled it
> >
> > drivers/net/wireless/realtek/rtw88/Kconfig | 3 +
> > drivers/net/wireless/realtek/rtw88/Makefile | 2 +
> > drivers/net/wireless/realtek/rtw88/mac.c | 3 +
> > drivers/net/wireless/realtek/rtw88/main.c | 4 +
> > drivers/net/wireless/realtek/rtw88/main.h | 4 +
> > drivers/net/wireless/realtek/rtw88/reg.h | 1 +
> > drivers/net/wireless/realtek/rtw88/tx.h | 31 +
> > drivers/net/wireless/realtek/rtw88/usb.c | 918 ++++++++++++++++++++
> > drivers/net/wireless/realtek/rtw88/usb.h | 107 +++
> > 9 files changed, 1073 insertions(+)
> > create mode 100644 drivers/net/wireless/realtek/rtw88/usb.c
> > create mode 100644 drivers/net/wireless/realtek/rtw88/usb.h
> >
> > diff --git a/drivers/net/wireless/realtek/rtw88/Kconfig b/drivers/net/wireless/realtek/rtw88/Kconfig
> > index e3d7cb6c12902..1624c5db69bac 100644
> > --- a/drivers/net/wireless/realtek/rtw88/Kconfig
> > +++ b/drivers/net/wireless/realtek/rtw88/Kconfig
> > @@ -16,6 +16,9 @@ config RTW88_CORE
> > config RTW88_PCI
> > tristate
> >
> > +config RTW88_USB
> > + tristate
> > +
> > config RTW88_8822B
> > tristate
> >
> > diff --git a/drivers/net/wireless/realtek/rtw88/Makefile b/drivers/net/wireless/realtek/rtw88/Makefile
> > index 834c66ec0af9e..9e095f8181483 100644
> > --- a/drivers/net/wireless/realtek/rtw88/Makefile
> > +++ b/drivers/net/wireless/realtek/rtw88/Makefile
> > @@ -45,4 +45,6 @@ obj-$(CONFIG_RTW88_8821CE) += rtw88_8821ce.o
> > rtw88_8821ce-objs := rtw8821ce.o
> >
> > obj-$(CONFIG_RTW88_PCI) += rtw88_pci.o
> > +obj-$(CONFIG_RTW88_USB) += rtw88_usb.o
> > rtw88_pci-objs := pci.o
> > +rtw88_usb-objs := usb.o
>
> nit: I prefer not interleaving with PCI.

Ok.

> > +static u32 rtw_usb_read(struct rtw_dev *rtwdev, u32 addr, u16 len)
> > +{
> > + struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
> > + struct usb_device *udev = rtwusb->udev;
> > + __le32 *data;
> > + unsigned long flags;
> > + int ret;
> > + static int count;
> > +
> > + spin_lock_irqsave(&rtwusb->usb_lock, flags);
> > +
> > + rtwusb->usb_data_index++;
> > + rtwusb->usb_data_index &= (RTW_USB_MAX_RXTX_COUNT - 1);
> > +
> > + spin_unlock_irqrestore(&rtwusb->usb_lock, flags);
> > +
> > + data = &rtwusb->usb_data[rtwusb->usb_data_index];
>
> Don't you need to hold &rtwusb->usb_lock to access rtwusb->usb_data_index?
> rtw_usb_write() has similar code.

Right. Will rewrite to:

spin_lock_irqsave(&rtwusb->usb_lock, flags);

idx = rtwusb->usb_data_index;
rtwusb->usb_data_index = (idx + 1) & (RTW_USB_MAX_RXTX_COUNT - 1);

spin_unlock_irqrestore(&rtwusb->usb_lock, flags);

data = &rtwusb->usb_data[idx];

> > +static void rtw_usb_write_port_tx_complete(struct urb *urb)
> > +{
> > + struct rtw_usb_txcb *txcb = urb->context;
> > + struct rtw_dev *rtwdev = txcb->rtwdev;
> > + struct ieee80211_hw *hw = rtwdev->hw;
> > +
> > + while (true) {
>
> Is it possible to have a hard limit to prevent unexpected infinite loop?

Yes, that would be possible, but do you think it's necessary?

Each *txcb is used only once, It's allocated in rtw_usb_tx_agg_skb() and
&txcb->tx_ack_queue is filled with a limited number of skbs there. These
skbs is then iterated over in rtw_usb_write_port_tx_complete(), so I don't
see a way how we could end up in an infinite loop here.

It's not that &txcb->tx_ack_queue is filled in a concurrent thread while we
try to catch up in rtw_usb_write_port_tx_complete().

> > + skb_head = dev_alloc_skb(RTW_USB_MAX_XMITBUF_SZ);
> > + if (!skb_head) {
> > + skb_head = skb_iter;
> > + goto queue;
> > + }
> > +
> > + data_ptr = skb_head->data;
> > +
> > + while (skb_iter) {
> > + unsigned long flags;
> > +
> > + memcpy(data_ptr, skb_iter->data, skb_iter->len);
> > + skb_put(skb_head, skb_iter->len + align_next);
>
> skb_put(skb_head, align_next);
> skb_put_data(skb_head, skb_iter->data, skb_iter->len);
>
> Then, don't need to maintain 'data_ptr'.

Right. Looks much better this way.

> > + error = usb_submit_urb(rxcb->rx_urb, GFP_ATOMIC);
> > + if (error) {
> > + kfree_skb(rxcb->rx_skb);
> > + if (error != -ENODEV)
> > + rtw_err(rtwdev, "Err sending rx data urb %d\n",
> > + error);
>
> nit: straighten rtw_err()

Ok.

Sascha

--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |

2022-11-28 13:44:42

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH v3 07/11] rtw88: Add common USB chip support

Sascha Hauer <[email protected]> writes:

>> > +static void rtw_usb_write_port_tx_complete(struct urb *urb)
>> > +{
>> > + struct rtw_usb_txcb *txcb = urb->context;
>> > + struct rtw_dev *rtwdev = txcb->rtwdev;
>> > + struct ieee80211_hw *hw = rtwdev->hw;
>> > +
>> > + while (true) {
>>
>> Is it possible to have a hard limit to prevent unexpected infinite loop?
>
> Yes, that would be possible, but do you think it's necessary?

It's a common advice to have a limit for loops in kernel.

> Each *txcb is used only once, It's allocated in rtw_usb_tx_agg_skb() and
> &txcb->tx_ack_queue is filled with a limited number of skbs there. These
> skbs is then iterated over in rtw_usb_write_port_tx_complete(), so I don't
> see a way how we could end up in an infinite loop here.

Everyone always say that their code is bugfree ;) More seriously though,
even if it would be bugfree now someone else can add buggy code later.
So much better to have a limit for the loop.

--
https://patchwork.kernel.org/project/linux-wireless/list/

https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches