diff --git a/packages/linux/patches/default/linux-121-rtw88-linux-next-6-2.patch b/packages/linux/patches/default/linux-121-rtw88-linux-next-6-2.patch deleted file mode 100644 index 7ea68b3cd6..0000000000 --- a/packages/linux/patches/default/linux-121-rtw88-linux-next-6-2.patch +++ /dev/null @@ -1,2717 +0,0 @@ -From 823092a53556ebf8656623d0e857626d30fe1e18 Mon Sep 17 00:00:00 2001 -From: Ji-Pin Jou -Date: Thu, 24 Nov 2022 14:44:42 +0800 -Subject: wifi: rtw88: fix race condition when doing H2C command - -For SDIO/USB interface, since the tranferring speed is slower than -that in PCIE, it may have race condition when the driver sets down -H2C command to the FW. - -In the function rtw_fw_send_h2c_command, before the patch, box_reg -is written first, then box_ex_reg is written. FW starts to work and -fetch the value of box_ex_reg, when the most significant byte of -box_reg(4 bytes) is written. Meanwhile, for SDIO/USB interface, -since the transferring speed is slow, the driver is still in writing -the new value of box_ex_reg through the bus, and FW may get the -wrong value of box_ex_reg at the moment. - -To prevent the above driver/FW racing situation, box_ex_reg is -written first then box_reg. Furthermore, it is written in 4 bytes at -a time, instead of written in one byte one by one. It can increase -the speed for SDIO/USB interface. - -Signed-off-by: Ji-Pin Jou -Signed-off-by: Ping-Ke Shih -Tested-by: Sascha Hauer -Signed-off-by: Kalle Valo -Link: https://lore.kernel.org/r/20221124064442.28042-1-pkshih@realtek.com ---- - drivers/net/wireless/realtek/rtw88/fw.c | 8 +++----- - drivers/net/wireless/realtek/rtw88/fw.h | 5 +++++ - 2 files changed, 8 insertions(+), 5 deletions(-) - -diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c -index 0b5f903c0f366..b290811d75e1c 100644 ---- a/drivers/net/wireless/realtek/rtw88/fw.c -+++ b/drivers/net/wireless/realtek/rtw88/fw.c -@@ -311,10 +311,10 @@ EXPORT_SYMBOL(rtw_fw_c2h_cmd_isr); - static void rtw_fw_send_h2c_command(struct rtw_dev *rtwdev, - u8 *h2c) - { -+ struct rtw_h2c_cmd *h2c_cmd = (struct rtw_h2c_cmd *)h2c; - u8 box; - u8 box_state; - u32 box_reg, box_ex_reg; -- int idx; - int ret; - - rtw_dbg(rtwdev, RTW_DBG_FW, -@@ -356,10 +356,8 @@ static void rtw_fw_send_h2c_command(struct rtw_dev *rtwdev, - goto out; - } - -- for (idx = 0; idx < 4; idx++) -- rtw_write8(rtwdev, box_reg + idx, h2c[idx]); -- for (idx = 0; idx < 4; idx++) -- rtw_write8(rtwdev, box_ex_reg + idx, h2c[idx + 4]); -+ rtw_write32(rtwdev, box_ex_reg, le32_to_cpu(h2c_cmd->msg_ext)); -+ rtw_write32(rtwdev, box_reg, le32_to_cpu(h2c_cmd->msg)); - - if (++rtwdev->h2c.last_box_num >= 4) - rtwdev->h2c.last_box_num = 0; -diff --git a/drivers/net/wireless/realtek/rtw88/fw.h b/drivers/net/wireless/realtek/rtw88/fw.h -index a5a965803a3cc..bca610dc99ab7 100644 ---- a/drivers/net/wireless/realtek/rtw88/fw.h -+++ b/drivers/net/wireless/realtek/rtw88/fw.h -@@ -81,6 +81,11 @@ struct rtw_c2h_adaptivity { - u8 option; - } __packed; - -+struct rtw_h2c_cmd { -+ __le32 msg; -+ __le32 msg_ext; -+} __packed; -+ - enum rtw_rsvd_packet_type { - RSVD_BEACON, - RSVD_DUMMY, --- -cgit - -From 1d89660494402168565e0637268486ae28bad642 Mon Sep 17 00:00:00 2001 -From: Sascha Hauer -Date: Fri, 2 Dec 2022 09:12:14 +0100 -Subject: wifi: rtw88: print firmware type in info message - -It's confusing to read two different firmware versions in the syslog -for the same device: - -rtw_8822cu 2-1:1.2: Firmware version 9.9.4, H2C version 15 -rtw_8822cu 2-1:1.2: Firmware version 9.9.11, H2C version 15 - -Print the firmware type in this message to make clear these are really -two different firmwares for different purposes: - -rtw_8822cu 1-1.4:1.2: WOW Firmware version 9.9.4, H2C version 15 -rtw_8822cu 1-1.4:1.2: Firmware version 9.9.11, H2C version 15 - -Signed-off-by: Sascha Hauer -Reviewed-by: Ping-Ke Shih -Signed-off-by: Kalle Valo -Link: https://lore.kernel.org/r/20221202081224.2779981-2-s.hauer@pengutronix.de ---- - drivers/net/wireless/realtek/rtw88/main.c | 4 +++- - drivers/net/wireless/realtek/rtw88/main.h | 1 + - 2 files changed, 4 insertions(+), 1 deletion(-) - -diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c -index 67151dbf83842..a7331872e8530 100644 ---- a/drivers/net/wireless/realtek/rtw88/main.c -+++ b/drivers/net/wireless/realtek/rtw88/main.c -@@ -1731,7 +1731,8 @@ static void rtw_load_firmware_cb(const struct firmware *firmware, void *context) - update_firmware_info(rtwdev, fw); - complete_all(&fw->completion); - -- rtw_info(rtwdev, "Firmware version %u.%u.%u, H2C version %u\n", -+ rtw_info(rtwdev, "%sFirmware version %u.%u.%u, H2C version %u\n", -+ fw->type == RTW_WOWLAN_FW ? "WOW " : "", - fw->version, fw->sub_version, fw->sub_index, fw->h2c_version); - } - -@@ -1757,6 +1758,7 @@ static int rtw_load_firmware(struct rtw_dev *rtwdev, enum rtw_fw_type type) - return -ENOENT; - } - -+ fw->type = type; - fw->rtwdev = rtwdev; - init_completion(&fw->completion); - -diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h -index bccd7b28f60c7..6e5875f6d07f4 100644 ---- a/drivers/net/wireless/realtek/rtw88/main.h -+++ b/drivers/net/wireless/realtek/rtw88/main.h -@@ -1851,6 +1851,7 @@ struct rtw_fw_state { - u16 h2c_version; - u32 feature; - u32 feature_ext; -+ enum rtw_fw_type type; - }; - - enum rtw_sar_sources { --- -cgit - -From 69020957bcb783184af1a86c8483139557cec751 Mon Sep 17 00:00:00 2001 -From: Sascha Hauer -Date: Fri, 2 Dec 2022 09:12:15 +0100 -Subject: wifi: 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 -Reviewed-by: Ping-Ke Shih -Signed-off-by: Kalle Valo -Link: https://lore.kernel.org/r/20221202081224.2779981-3-s.hauer@pengutronix.de ---- - 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); - --- -cgit - -From d57ca103e54e2b3eea7e2603548c58bcc4155541 Mon Sep 17 00:00:00 2001 -From: Sascha Hauer -Date: Fri, 2 Dec 2022 09:12:16 +0100 -Subject: wifi: rtw88: Drop rf_lock - -The rtwdev->rf_lock spinlock protects the rf register accesses in -rtw_read_rf() and rtw_write_rf(). Most callers of these functions hold -rtwdev->mutex already with the exception of the callsites in the debugfs -code. The debugfs code doesn't justify an extra lock, so acquire the mutex -there as well before calling rf register accessors and drop the now -unnecessary spinlock. - -Signed-off-by: Sascha Hauer -Reviewed-by: Ping-Ke Shih -Signed-off-by: Kalle Valo -Link: https://lore.kernel.org/r/20221202081224.2779981-4-s.hauer@pengutronix.de ---- - drivers/net/wireless/realtek/rtw88/debug.c | 11 +++++++++++ - drivers/net/wireless/realtek/rtw88/hci.h | 9 +++------ - drivers/net/wireless/realtek/rtw88/main.c | 1 - - drivers/net/wireless/realtek/rtw88/main.h | 3 --- - 4 files changed, 14 insertions(+), 10 deletions(-) - -diff --git a/drivers/net/wireless/realtek/rtw88/debug.c b/drivers/net/wireless/realtek/rtw88/debug.c -index 9ebe544e51d0d..70e19f2a1a355 100644 ---- a/drivers/net/wireless/realtek/rtw88/debug.c -+++ b/drivers/net/wireless/realtek/rtw88/debug.c -@@ -144,7 +144,9 @@ static int rtw_debugfs_get_rf_read(struct seq_file *m, void *v) - addr = debugfs_priv->rf_addr; - mask = debugfs_priv->rf_mask; - -+ mutex_lock(&rtwdev->mutex); - val = rtw_read_rf(rtwdev, path, addr, mask); -+ mutex_unlock(&rtwdev->mutex); - - seq_printf(m, "rf_read path:%d addr:0x%08x mask:0x%08x val=0x%08x\n", - path, addr, mask, val); -@@ -414,7 +416,9 @@ static ssize_t rtw_debugfs_set_rf_write(struct file *filp, - return count; - } - -+ mutex_lock(&rtwdev->mutex); - rtw_write_rf(rtwdev, path, addr, mask, val); -+ mutex_unlock(&rtwdev->mutex); - rtw_dbg(rtwdev, RTW_DBG_DEBUGFS, - "write_rf path:%d addr:0x%08x mask:0x%08x, val:0x%08x\n", - path, addr, mask, val); -@@ -519,6 +523,8 @@ static int rtw_debug_get_rf_dump(struct seq_file *m, void *v) - u32 addr, offset, data; - u8 path; - -+ mutex_lock(&rtwdev->mutex); -+ - for (path = 0; path < rtwdev->hal.rf_path_num; path++) { - seq_printf(m, "RF path:%d\n", path); - for (addr = 0; addr < 0x100; addr += 4) { -@@ -533,6 +539,8 @@ static int rtw_debug_get_rf_dump(struct seq_file *m, void *v) - seq_puts(m, "\n"); - } - -+ mutex_unlock(&rtwdev->mutex); -+ - return 0; - } - -@@ -1026,6 +1034,8 @@ static void dump_gapk_status(struct rtw_dev *rtwdev, struct seq_file *m) - dm_info->dm_flags & BIT(RTW_DM_CAP_TXGAPK) ? '-' : '+', - rtw_dm_cap_strs[RTW_DM_CAP_TXGAPK]); - -+ mutex_lock(&rtwdev->mutex); -+ - for (path = 0; path < rtwdev->hal.rf_path_num; path++) { - val = rtw_read_rf(rtwdev, path, RF_GAINTX, RFREG_MASK); - seq_printf(m, "path %d:\n0x%x = 0x%x\n", path, RF_GAINTX, val); -@@ -1035,6 +1045,7 @@ static void dump_gapk_status(struct rtw_dev *rtwdev, struct seq_file *m) - txgapk->rf3f_fs[path][i], i); - seq_puts(m, "\n"); - } -+ mutex_unlock(&rtwdev->mutex); - } - - static int rtw_debugfs_get_dm_cap(struct seq_file *m, void *v) -diff --git a/drivers/net/wireless/realtek/rtw88/hci.h b/drivers/net/wireless/realtek/rtw88/hci.h -index 4c6fc6fb3f83b..830d7532f2a35 100644 ---- a/drivers/net/wireless/realtek/rtw88/hci.h -+++ b/drivers/net/wireless/realtek/rtw88/hci.h -@@ -166,12 +166,11 @@ static inline u32 - rtw_read_rf(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, - u32 addr, u32 mask) - { -- unsigned long flags; - u32 val; - -- spin_lock_irqsave(&rtwdev->rf_lock, flags); -+ lockdep_assert_held(&rtwdev->mutex); -+ - val = rtwdev->chip->ops->read_rf(rtwdev, rf_path, addr, mask); -- spin_unlock_irqrestore(&rtwdev->rf_lock, flags); - - return val; - } -@@ -180,11 +179,9 @@ static inline void - rtw_write_rf(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path, - u32 addr, u32 mask, u32 data) - { -- unsigned long flags; -+ lockdep_assert_held(&rtwdev->mutex); - -- spin_lock_irqsave(&rtwdev->rf_lock, flags); - rtwdev->chip->ops->write_rf(rtwdev, rf_path, addr, mask, data); -- spin_unlock_irqrestore(&rtwdev->rf_lock, flags); - } - - static inline u32 -diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c -index a7331872e8530..710ddb0283c82 100644 ---- a/drivers/net/wireless/realtek/rtw88/main.c -+++ b/drivers/net/wireless/realtek/rtw88/main.c -@@ -2067,7 +2067,6 @@ int rtw_core_init(struct rtw_dev *rtwdev) - skb_queue_head_init(&rtwdev->coex.queue); - skb_queue_head_init(&rtwdev->tx_report.queue); - -- spin_lock_init(&rtwdev->rf_lock); - spin_lock_init(&rtwdev->h2c.lock); - spin_lock_init(&rtwdev->txq_lock); - spin_lock_init(&rtwdev->tx_report.q_lock); -diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h -index 6e5875f6d07f4..f24d17f482aaa 100644 ---- a/drivers/net/wireless/realtek/rtw88/main.h -+++ b/drivers/net/wireless/realtek/rtw88/main.h -@@ -1995,9 +1995,6 @@ struct rtw_dev { - /* ensures exclusive access from mac80211 callbacks */ - struct mutex mutex; - -- /* read/write rf register */ -- spinlock_t rf_lock; -- - /* watch dog every 2 sec */ - struct delayed_work watch_dog_work; - u32 watch_dog_cnt; --- -cgit - -From 1e2701f4079a7906ff3fb43a315925d303e289d8 Mon Sep 17 00:00:00 2001 -From: Sascha Hauer -Date: Fri, 2 Dec 2022 09:12:17 +0100 -Subject: wifi: rtw88: Drop h2c.lock - -The h2c.lock spinlock is used in rtw_fw_send_h2c_command() and -rtw_fw_send_h2c_packet(). Most callers call this with rtwdev->mutex -held, except from one callsite in the debugfs code. The debugfs code -alone doesn't justify the extra lock, so acquire rtwdev->mutex in -debugfs and drop the now unnecessary spinlock. - -Signed-off-by: Sascha Hauer -Signed-off-by: Kalle Valo -Link: https://lore.kernel.org/r/20221202081224.2779981-5-s.hauer@pengutronix.de ---- - drivers/net/wireless/realtek/rtw88/debug.c | 2 ++ - drivers/net/wireless/realtek/rtw88/fw.c | 13 ++++--------- - drivers/net/wireless/realtek/rtw88/main.c | 1 - - drivers/net/wireless/realtek/rtw88/main.h | 2 -- - 4 files changed, 6 insertions(+), 12 deletions(-) - -diff --git a/drivers/net/wireless/realtek/rtw88/debug.c b/drivers/net/wireless/realtek/rtw88/debug.c -index 70e19f2a1a355..f5b8a77ebc67b 100644 ---- a/drivers/net/wireless/realtek/rtw88/debug.c -+++ b/drivers/net/wireless/realtek/rtw88/debug.c -@@ -392,7 +392,9 @@ static ssize_t rtw_debugfs_set_h2c(struct file *filp, - return -EINVAL; - } - -+ mutex_lock(&rtwdev->mutex); - rtw_fw_h2c_cmd_dbg(rtwdev, param); -+ mutex_unlock(&rtwdev->mutex); - - return count; - } -diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c -index 5e760c884f89d..82295ac6402ee 100644 ---- a/drivers/net/wireless/realtek/rtw88/fw.c -+++ b/drivers/net/wireless/realtek/rtw88/fw.c -@@ -322,7 +322,7 @@ static void rtw_fw_send_h2c_command(struct rtw_dev *rtwdev, - h2c[3], h2c[2], h2c[1], h2c[0], - h2c[7], h2c[6], h2c[5], h2c[4]); - -- spin_lock(&rtwdev->h2c.lock); -+ lockdep_assert_held(&rtwdev->mutex); - - box = rtwdev->h2c.last_box_num; - switch (box) { -@@ -344,7 +344,7 @@ static void rtw_fw_send_h2c_command(struct rtw_dev *rtwdev, - break; - default: - WARN(1, "invalid h2c mail box number\n"); -- goto out; -+ return; - } - - ret = read_poll_timeout_atomic(rtw_read8, box_state, -@@ -353,7 +353,7 @@ static void rtw_fw_send_h2c_command(struct rtw_dev *rtwdev, - - if (ret) { - rtw_err(rtwdev, "failed to send h2c command\n"); -- goto out; -+ return; - } - - rtw_write32(rtwdev, box_ex_reg, le32_to_cpu(h2c_cmd->msg_ext)); -@@ -361,9 +361,6 @@ static void rtw_fw_send_h2c_command(struct rtw_dev *rtwdev, - - if (++rtwdev->h2c.last_box_num >= 4) - rtwdev->h2c.last_box_num = 0; -- --out: -- spin_unlock(&rtwdev->h2c.lock); - } - - void rtw_fw_h2c_cmd_dbg(struct rtw_dev *rtwdev, u8 *h2c) -@@ -375,15 +372,13 @@ static void rtw_fw_send_h2c_packet(struct rtw_dev *rtwdev, u8 *h2c_pkt) - { - int ret; - -- spin_lock(&rtwdev->h2c.lock); -+ lockdep_assert_held(&rtwdev->mutex); - - FW_OFFLOAD_H2C_SET_SEQ_NUM(h2c_pkt, rtwdev->h2c.seq); - ret = rtw_hci_write_data_h2c(rtwdev, h2c_pkt, H2C_PKT_SIZE); - if (ret) - rtw_err(rtwdev, "failed to send h2c packet\n"); - rtwdev->h2c.seq++; -- -- spin_unlock(&rtwdev->h2c.lock); - } - - void -diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c -index 710ddb0283c82..c98e56890401c 100644 ---- a/drivers/net/wireless/realtek/rtw88/main.c -+++ b/drivers/net/wireless/realtek/rtw88/main.c -@@ -2067,7 +2067,6 @@ int rtw_core_init(struct rtw_dev *rtwdev) - skb_queue_head_init(&rtwdev->coex.queue); - skb_queue_head_init(&rtwdev->tx_report.queue); - -- spin_lock_init(&rtwdev->h2c.lock); - spin_lock_init(&rtwdev->txq_lock); - spin_lock_init(&rtwdev->tx_report.q_lock); - -diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h -index f24d17f482aaa..4b57542bef1e9 100644 ---- a/drivers/net/wireless/realtek/rtw88/main.h -+++ b/drivers/net/wireless/realtek/rtw88/main.h -@@ -2020,8 +2020,6 @@ struct rtw_dev { - struct { - /* incicate the mail box to use with fw */ - u8 last_box_num; -- /* protect to send h2c to fw */ -- spinlock_t lock; - u32 seq; - } h2c; - --- -cgit - -From 8647f7f0b9080bc2d2f6e02524782f2f02f159bc Mon Sep 17 00:00:00 2001 -From: Sascha Hauer -Date: Fri, 2 Dec 2022 09:12:18 +0100 -Subject: wifi: rtw88: Drop coex mutex - -coex->mutex is used in rtw_coex_info_request() only. Most callers of this -function hold rtwdev->mutex already, except for one callsite in the -debugfs code. The debugfs code alone doesn't justify the extra lock, so -acquire rtwdev->mutex there as well and drop the now unnecessary -spinlock. - -Signed-off-by: Sascha Hauer -Signed-off-by: Kalle Valo -Link: https://lore.kernel.org/r/20221202081224.2779981-6-s.hauer@pengutronix.de ---- - drivers/net/wireless/realtek/rtw88/coex.c | 3 +-- - drivers/net/wireless/realtek/rtw88/debug.c | 2 ++ - drivers/net/wireless/realtek/rtw88/main.c | 2 -- - drivers/net/wireless/realtek/rtw88/main.h | 2 -- - 4 files changed, 3 insertions(+), 6 deletions(-) - -diff --git a/drivers/net/wireless/realtek/rtw88/coex.c b/drivers/net/wireless/realtek/rtw88/coex.c -index 6276ad6242991..38697237ee5f0 100644 ---- a/drivers/net/wireless/realtek/rtw88/coex.c -+++ b/drivers/net/wireless/realtek/rtw88/coex.c -@@ -633,7 +633,7 @@ static struct sk_buff *rtw_coex_info_request(struct rtw_dev *rtwdev, - struct rtw_coex *coex = &rtwdev->coex; - struct sk_buff *skb_resp = NULL; - -- mutex_lock(&coex->mutex); -+ lockdep_assert_held(&rtwdev->mutex); - - rtw_fw_query_bt_mp_info(rtwdev, req); - -@@ -650,7 +650,6 @@ static struct sk_buff *rtw_coex_info_request(struct rtw_dev *rtwdev, - } - - out: -- mutex_unlock(&coex->mutex); - return skb_resp; - } - -diff --git a/drivers/net/wireless/realtek/rtw88/debug.c b/drivers/net/wireless/realtek/rtw88/debug.c -index f5b8a77ebc67b..fa3d73b333ba0 100644 ---- a/drivers/net/wireless/realtek/rtw88/debug.c -+++ b/drivers/net/wireless/realtek/rtw88/debug.c -@@ -841,7 +841,9 @@ static int rtw_debugfs_get_coex_info(struct seq_file *m, void *v) - struct rtw_debugfs_priv *debugfs_priv = m->private; - struct rtw_dev *rtwdev = debugfs_priv->rtwdev; - -+ mutex_lock(&rtwdev->mutex); - rtw_coex_display_coex_info(rtwdev, m); -+ mutex_unlock(&rtwdev->mutex); - - return 0; - } -diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c -index c98e56890401c..0a2ce7f50f412 100644 ---- a/drivers/net/wireless/realtek/rtw88/main.c -+++ b/drivers/net/wireless/realtek/rtw88/main.c -@@ -2071,7 +2071,6 @@ int rtw_core_init(struct rtw_dev *rtwdev) - spin_lock_init(&rtwdev->tx_report.q_lock); - - mutex_init(&rtwdev->mutex); -- mutex_init(&rtwdev->coex.mutex); - mutex_init(&rtwdev->hal.tx_power_mutex); - - init_waitqueue_head(&rtwdev->coex.wait); -@@ -2143,7 +2142,6 @@ void rtw_core_deinit(struct rtw_dev *rtwdev) - } - - mutex_destroy(&rtwdev->mutex); -- mutex_destroy(&rtwdev->coex.mutex); - mutex_destroy(&rtwdev->hal.tx_power_mutex); - } - EXPORT_SYMBOL(rtw_core_deinit); -diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h -index 4b57542bef1e9..77fd48b6cc453 100644 ---- a/drivers/net/wireless/realtek/rtw88/main.h -+++ b/drivers/net/wireless/realtek/rtw88/main.h -@@ -1501,8 +1501,6 @@ struct rtw_coex_stat { - }; - - struct rtw_coex { -- /* protects coex info request section */ -- struct mutex mutex; - struct sk_buff_head queue; - wait_queue_head_t wait; - --- -cgit - -From 78d5bf925f30bf9f79a69ce77386902672defe68 Mon Sep 17 00:00:00 2001 -From: Sascha Hauer -Date: Fri, 2 Dec 2022 09:12:19 +0100 -Subject: wifi: rtw88: iterate over vif/sta list non-atomically - -The driver uses ieee80211_iterate_active_interfaces_atomic() -and ieee80211_iterate_stations_atomic() in several places and does -register accesses in the iterators. This doesn't cope with upcoming -USB support as registers can only be accessed non-atomically. - -Split these into a two stage process: First use the atomic iterator -functions to collect all active interfaces or stations on a list, then -iterate over the list non-atomically and call the iterator on each -entry. - -Signed-off-by: Sascha Hauer -Suggested-by: Ping-Ke shih -Reviewed-by: Ping-Ke Shih -Signed-off-by: Kalle Valo -Link: https://lore.kernel.org/r/20221202081224.2779981-7-s.hauer@pengutronix.de ---- - drivers/net/wireless/realtek/rtw88/phy.c | 6 +- - drivers/net/wireless/realtek/rtw88/ps.c | 2 +- - drivers/net/wireless/realtek/rtw88/util.c | 103 ++++++++++++++++++++++++++++++ - drivers/net/wireless/realtek/rtw88/util.h | 12 +++- - 4 files changed, 116 insertions(+), 7 deletions(-) - -diff --git a/drivers/net/wireless/realtek/rtw88/phy.c b/drivers/net/wireless/realtek/rtw88/phy.c -index bd7d05e080848..128e75a81bf3c 100644 ---- a/drivers/net/wireless/realtek/rtw88/phy.c -+++ b/drivers/net/wireless/realtek/rtw88/phy.c -@@ -300,7 +300,7 @@ static void rtw_phy_stat_rssi(struct rtw_dev *rtwdev) - - data.rtwdev = rtwdev; - data.min_rssi = U8_MAX; -- rtw_iterate_stas_atomic(rtwdev, rtw_phy_stat_rssi_iter, &data); -+ rtw_iterate_stas(rtwdev, rtw_phy_stat_rssi_iter, &data); - - dm_info->pre_min_rssi = dm_info->min_rssi; - dm_info->min_rssi = data.min_rssi; -@@ -544,7 +544,7 @@ static void rtw_phy_ra_info_update(struct rtw_dev *rtwdev) - if (rtwdev->watch_dog_cnt & 0x3) - return; - -- rtw_iterate_stas_atomic(rtwdev, rtw_phy_ra_info_update_iter, rtwdev); -+ rtw_iterate_stas(rtwdev, rtw_phy_ra_info_update_iter, rtwdev); - } - - static u32 rtw_phy_get_rrsr_mask(struct rtw_dev *rtwdev, u8 rate_idx) -@@ -597,7 +597,7 @@ static void rtw_phy_rrsr_update(struct rtw_dev *rtwdev) - struct rtw_dm_info *dm_info = &rtwdev->dm_info; - - dm_info->rrsr_mask_min = RRSR_RATE_ORDER_MAX; -- rtw_iterate_stas_atomic(rtwdev, rtw_phy_rrsr_mask_min_iter, rtwdev); -+ rtw_iterate_stas(rtwdev, rtw_phy_rrsr_mask_min_iter, rtwdev); - rtw_write32(rtwdev, REG_RRSR, dm_info->rrsr_val_init & dm_info->rrsr_mask_min); - } - -diff --git a/drivers/net/wireless/realtek/rtw88/ps.c b/drivers/net/wireless/realtek/rtw88/ps.c -index c93da743681fc..11594940d6b00 100644 ---- a/drivers/net/wireless/realtek/rtw88/ps.c -+++ b/drivers/net/wireless/realtek/rtw88/ps.c -@@ -61,7 +61,7 @@ int rtw_leave_ips(struct rtw_dev *rtwdev) - return ret; - } - -- rtw_iterate_vifs_atomic(rtwdev, rtw_restore_port_cfg_iter, rtwdev); -+ rtw_iterate_vifs(rtwdev, rtw_restore_port_cfg_iter, rtwdev); - - rtw_coex_ips_notify(rtwdev, COEX_IPS_LEAVE); - -diff --git a/drivers/net/wireless/realtek/rtw88/util.c b/drivers/net/wireless/realtek/rtw88/util.c -index cdfd66a85075a..ff3c269fb1a72 100644 ---- a/drivers/net/wireless/realtek/rtw88/util.c -+++ b/drivers/net/wireless/realtek/rtw88/util.c -@@ -105,3 +105,106 @@ void rtw_desc_to_mcsrate(u16 rate, u8 *mcs, u8 *nss) - *mcs = rate - DESC_RATEMCS0; - } - } -+ -+struct rtw_stas_entry { -+ struct list_head list; -+ struct ieee80211_sta *sta; -+}; -+ -+struct rtw_iter_stas_data { -+ struct rtw_dev *rtwdev; -+ struct list_head list; -+}; -+ -+static void rtw_collect_sta_iter(void *data, struct ieee80211_sta *sta) -+{ -+ struct rtw_iter_stas_data *iter_stas = data; -+ struct rtw_stas_entry *stas_entry; -+ -+ stas_entry = kmalloc(sizeof(*stas_entry), GFP_ATOMIC); -+ if (!stas_entry) -+ return; -+ -+ stas_entry->sta = sta; -+ list_add_tail(&stas_entry->list, &iter_stas->list); -+} -+ -+void rtw_iterate_stas(struct rtw_dev *rtwdev, -+ void (*iterator)(void *data, -+ struct ieee80211_sta *sta), -+ void *data) -+{ -+ struct rtw_iter_stas_data iter_data; -+ struct rtw_stas_entry *sta_entry, *tmp; -+ -+ /* &rtwdev->mutex makes sure no stations can be removed between -+ * collecting the stations and iterating over them. -+ */ -+ lockdep_assert_held(&rtwdev->mutex); -+ -+ iter_data.rtwdev = rtwdev; -+ INIT_LIST_HEAD(&iter_data.list); -+ -+ ieee80211_iterate_stations_atomic(rtwdev->hw, rtw_collect_sta_iter, -+ &iter_data); -+ -+ list_for_each_entry_safe(sta_entry, tmp, &iter_data.list, -+ list) { -+ list_del_init(&sta_entry->list); -+ iterator(data, sta_entry->sta); -+ kfree(sta_entry); -+ } -+} -+ -+struct rtw_vifs_entry { -+ struct list_head list; -+ struct ieee80211_vif *vif; -+ u8 mac[ETH_ALEN]; -+}; -+ -+struct rtw_iter_vifs_data { -+ struct rtw_dev *rtwdev; -+ struct list_head list; -+}; -+ -+static void rtw_collect_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) -+{ -+ struct rtw_iter_vifs_data *iter_stas = data; -+ struct rtw_vifs_entry *vifs_entry; -+ -+ vifs_entry = kmalloc(sizeof(*vifs_entry), GFP_ATOMIC); -+ if (!vifs_entry) -+ return; -+ -+ vifs_entry->vif = vif; -+ ether_addr_copy(vifs_entry->mac, mac); -+ list_add_tail(&vifs_entry->list, &iter_stas->list); -+} -+ -+void rtw_iterate_vifs(struct rtw_dev *rtwdev, -+ void (*iterator)(void *data, u8 *mac, -+ struct ieee80211_vif *vif), -+ void *data) -+{ -+ struct rtw_iter_vifs_data iter_data; -+ struct rtw_vifs_entry *vif_entry, *tmp; -+ -+ /* &rtwdev->mutex makes sure no interfaces can be removed between -+ * collecting the interfaces and iterating over them. -+ */ -+ lockdep_assert_held(&rtwdev->mutex); -+ -+ iter_data.rtwdev = rtwdev; -+ INIT_LIST_HEAD(&iter_data.list); -+ -+ ieee80211_iterate_active_interfaces_atomic(rtwdev->hw, -+ IEEE80211_IFACE_ITER_NORMAL, -+ rtw_collect_vif_iter, &iter_data); -+ -+ list_for_each_entry_safe(vif_entry, tmp, &iter_data.list, -+ list) { -+ list_del_init(&vif_entry->list); -+ iterator(data, vif_entry->mac, vif_entry->vif); -+ kfree(vif_entry); -+ } -+} -diff --git a/drivers/net/wireless/realtek/rtw88/util.h b/drivers/net/wireless/realtek/rtw88/util.h -index 0c23b5069be0b..dc89655254002 100644 ---- a/drivers/net/wireless/realtek/rtw88/util.h -+++ b/drivers/net/wireless/realtek/rtw88/util.h -@@ -7,9 +7,6 @@ - - struct rtw_dev; - --#define rtw_iterate_vifs(rtwdev, iterator, data) \ -- ieee80211_iterate_active_interfaces(rtwdev->hw, \ -- IEEE80211_IFACE_ITER_NORMAL, iterator, data) - #define rtw_iterate_vifs_atomic(rtwdev, iterator, data) \ - ieee80211_iterate_active_interfaces_atomic(rtwdev->hw, \ - IEEE80211_IFACE_ITER_NORMAL, iterator, data) -@@ -20,6 +17,15 @@ struct rtw_dev; - #define rtw_iterate_keys_rcu(rtwdev, vif, iterator, data) \ - ieee80211_iter_keys_rcu((rtwdev)->hw, vif, iterator, data) - -+void rtw_iterate_vifs(struct rtw_dev *rtwdev, -+ void (*iterator)(void *data, u8 *mac, -+ struct ieee80211_vif *vif), -+ void *data); -+void rtw_iterate_stas(struct rtw_dev *rtwdev, -+ void (*iterator)(void *data, -+ struct ieee80211_sta *sta), -+ void *data); -+ - static inline u8 *get_hdr_bssid(struct ieee80211_hdr *hdr) - { - __le16 fc = hdr->frame_control; --- -cgit - -From a82dfd33d1237f6c0fb8a7077022189d1fc7ec98 Mon Sep 17 00:00:00 2001 -From: Sascha Hauer -Date: Fri, 2 Dec 2022 09:12:20 +0100 -Subject: wifi: 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 -Signed-off-by: Hans Ulli Kroll -Signed-off-by: Sascha Hauer -Signed-off-by: Kalle Valo -Link: https://lore.kernel.org/r/20221202081224.2779981-8-s.hauer@pengutronix.de ---- - drivers/net/wireless/realtek/rtw88/Kconfig | 3 + - drivers/net/wireless/realtek/rtw88/Makefile | 3 + - 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 | 911 ++++++++++++++++++++++++++++ - drivers/net/wireless/realtek/rtw88/usb.h | 107 ++++ - 9 files changed, 1067 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..2c2b0e5133cdf 100644 ---- a/drivers/net/wireless/realtek/rtw88/Makefile -+++ b/drivers/net/wireless/realtek/rtw88/Makefile -@@ -46,3 +46,6 @@ rtw88_8821ce-objs := rtw8821ce.o - - obj-$(CONFIG_RTW88_PCI) += rtw88_pci.o - rtw88_pci-objs := pci.o -+ -+obj-$(CONFIG_RTW88_USB) += rtw88_usb.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 c7e64f7036ac2..98777f294945f 100644 ---- a/drivers/net/wireless/realtek/rtw88/mac.c -+++ b/drivers/net/wireless/realtek/rtw88/mac.c -@@ -1048,6 +1048,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..4ef38279b64c9 ---- /dev/null -+++ b/drivers/net/wireless/realtek/rtw88/usb.c -@@ -0,0 +1,911 @@ -+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause -+/* Copyright(c) 2018-2019 Realtek Corporation -+ */ -+ -+#include -+#include -+#include -+#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 512 -+ -+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 idx, ret; -+ static int count; -+ -+ 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]; -+ -+ 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 idx, ret; -+ static int count; -+ -+ 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]; -+ -+ *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; -+ 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; -+ } -+ -+ while (skb_iter) { -+ unsigned long flags; -+ -+ skb_put(skb_head, align_next); -+ skb_put_data(skb_head, skb_iter->data, skb_iter->len); -+ -+ align_next = ALIGN(skb_iter->len, 8) - skb_iter->len; -+ -+ 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; -+ -+ 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..30647f0dd61c6 ---- /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 --- -cgit - -From aff5ffd718de23cb8603f2e229204670e2644334 Mon Sep 17 00:00:00 2001 -From: Sascha Hauer -Date: Fri, 2 Dec 2022 09:12:21 +0100 -Subject: wifi: 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 -Signed-off-by: Kalle Valo -Link: https://lore.kernel.org/r/20221202081224.2779981-9-s.hauer@pengutronix.de ---- - 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 +++++++++++ - drivers/net/wireless/realtek/rtw88/rtw8821cu.c | 50 ++++++++++++++++++++++++++ - 5 files changed, 103 insertions(+) - create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8821cu.c - -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 2c2b0e5133cdf..552661a638def 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 - 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..7a5cbdc31ef79 ---- /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 -+#include -+#include "main.h" -+#include "rtw8821c.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 "); -+MODULE_DESCRIPTION("Realtek 802.11ac wireless 8821cu driver"); -+MODULE_LICENSE("Dual BSD/GPL"); --- -cgit - -From 45794099f5e1d7abc5eb07e6eec7e1e5c6cb540d Mon Sep 17 00:00:00 2001 -From: Sascha Hauer -Date: Fri, 2 Dec 2022 09:12:22 +0100 -Subject: wifi: 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 -Signed-off-by: Kalle Valo -Link: https://lore.kernel.org/r/20221202081224.2779981-10-s.hauer@pengutronix.de ---- - drivers/net/wireless/realtek/rtw88/Kconfig | 11 ++++ - drivers/net/wireless/realtek/rtw88/Makefile | 3 + - drivers/net/wireless/realtek/rtw88/rtw8822b.c | 19 ++++++ - drivers/net/wireless/realtek/rtw88/rtw8822bu.c | 90 ++++++++++++++++++++++++++ - 4 files changed, 123 insertions(+) - create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8822bu.c - -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 552661a638def..6984bfb7a3170 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..ab620a0b1dfc6 ---- /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 -+#include -+#include "main.h" -+#include "rtw8822b.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"); --- -cgit - -From 07cef03b8d44dee7488de3d1585387e603c78676 Mon Sep 17 00:00:00 2001 -From: Sascha Hauer -Date: Fri, 2 Dec 2022 09:12:23 +0100 -Subject: wifi: rtw88: Add rtw8822cu chipset support - -Add support for the rtw8822cu chipset based on -https://github.com/ulli-kroll/rtw88-usb.git - -Signed-off-by: Sascha Hauer -Signed-off-by: Kalle Valo -Link: https://lore.kernel.org/r/20221202081224.2779981-11-s.hauer@pengutronix.de ---- - drivers/net/wireless/realtek/rtw88/Kconfig | 11 +++++++ - drivers/net/wireless/realtek/rtw88/Makefile | 3 ++ - drivers/net/wireless/realtek/rtw88/rtw8822c.c | 24 ++++++++++++++ - drivers/net/wireless/realtek/rtw88/rtw8822cu.c | 44 ++++++++++++++++++++++++++ - 4 files changed, 82 insertions(+) - create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8822cu.c - -diff --git a/drivers/net/wireless/realtek/rtw88/Kconfig b/drivers/net/wireless/realtek/rtw88/Kconfig -index 10f4e7f88b858..138289bc5ad0c 100644 ---- a/drivers/net/wireless/realtek/rtw88/Kconfig -+++ b/drivers/net/wireless/realtek/rtw88/Kconfig -@@ -64,6 +64,17 @@ config RTW88_8822CE - - 802.11ac PCIe wireless network adapter - -+config RTW88_8822CU -+ tristate "Realtek 8822CU USB wireless network adapter" -+ depends on USB -+ select RTW88_CORE -+ select RTW88_USB -+ select RTW88_8822C -+ help -+ Select this option will enable support for 8822CU chipset -+ -+ 802.11ac USB wireless network adapter -+ - config RTW88_8723DE - tristate "Realtek 8723DE PCI wireless network adapter" - depends on PCI -diff --git a/drivers/net/wireless/realtek/rtw88/Makefile b/drivers/net/wireless/realtek/rtw88/Makefile -index 6984bfb7a3170..fe2dd90204a78 100644 ---- a/drivers/net/wireless/realtek/rtw88/Makefile -+++ b/drivers/net/wireless/realtek/rtw88/Makefile -@@ -35,6 +35,9 @@ rtw88_8822c-objs := rtw8822c.o rtw8822c_table.o - obj-$(CONFIG_RTW88_8822CE) += rtw88_8822ce.o - rtw88_8822ce-objs := rtw8822ce.o - -+obj-$(CONFIG_RTW88_8822CU) += rtw88_8822cu.o -+rtw88_8822cu-objs := rtw8822cu.o -+ - obj-$(CONFIG_RTW88_8723D) += rtw88_8723d.o - rtw88_8723d-objs := rtw8723d.o rtw8723d_table.o - -diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c -index fccb15dfb9595..964e27887fe2d 100644 ---- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c -+++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c -@@ -29,6 +29,12 @@ static void rtw8822ce_efuse_parsing(struct rtw_efuse *efuse, - ether_addr_copy(efuse->addr, map->e.mac_addr); - } - -+static void rtw8822cu_efuse_parsing(struct rtw_efuse *efuse, -+ struct rtw8822c_efuse *map) -+{ -+ ether_addr_copy(efuse->addr, map->u.mac_addr); -+} -+ - static int rtw8822c_read_efuse(struct rtw_dev *rtwdev, u8 *log_map) - { - struct rtw_efuse *efuse = &rtwdev->efuse; -@@ -58,6 +64,9 @@ static int rtw8822c_read_efuse(struct rtw_dev *rtwdev, u8 *log_map) - case RTW_HCI_TYPE_PCIE: - rtw8822ce_efuse_parsing(efuse, map); - break; -+ case RTW_HCI_TYPE_USB: -+ rtw8822cu_efuse_parsing(efuse, map); -+ break; - default: - /* unsupported now */ - return -ENOTSUPP; -@@ -4557,6 +4566,18 @@ static void rtw8822c_adaptivity(struct rtw_dev *rtwdev) - rtw_phy_set_edcca_th(rtwdev, l2h, h2l); - } - -+static void rtw8822c_fill_txdesc_checksum(struct rtw_dev *rtwdev, -+ struct rtw_tx_pkt_info *pkt_info, -+ u8 *txdesc) -+{ -+ const struct rtw_chip_info *chip = rtwdev->chip; -+ size_t words; -+ -+ words = (pkt_info->pkt_offset * 8 + chip->tx_pkt_desc_sz) / 2; -+ -+ fill_txdesc_checksum_common(txdesc, words); -+} -+ - static const struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8822c[] = { - {0x0086, - RTW_PWR_CUT_ALL_MSK, -@@ -4895,6 +4916,8 @@ static const struct rtw_rfe_def rtw8822c_rfe_defs[] = { - [0] = RTW_DEF_RFE(8822c, 0, 0), - [1] = RTW_DEF_RFE(8822c, 0, 0), - [2] = RTW_DEF_RFE(8822c, 0, 0), -+ [3] = RTW_DEF_RFE(8822c, 0, 0), -+ [4] = RTW_DEF_RFE(8822c, 0, 0), - [5] = RTW_DEF_RFE(8822c, 0, 5), - [6] = RTW_DEF_RFE(8822c, 0, 0), - }; -@@ -4978,6 +5001,7 @@ static struct rtw_chip_ops rtw8822c_ops = { - .cfo_track = rtw8822c_cfo_track, - .config_tx_path = rtw8822c_config_tx_path, - .config_txrx_mode = rtw8822c_config_trx_mode, -+ .fill_txdesc_checksum = rtw8822c_fill_txdesc_checksum, - - .coex_set_init = rtw8822c_coex_cfg_init, - .coex_set_ant_switch = NULL, -diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822cu.c b/drivers/net/wireless/realtek/rtw88/rtw8822cu.c -new file mode 100644 -index 0000000000000..af28ca09d41fb ---- /dev/null -+++ b/drivers/net/wireless/realtek/rtw88/rtw8822cu.c -@@ -0,0 +1,44 @@ -+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause -+/* Copyright(c) 2018-2019 Realtek Corporation -+ */ -+ -+#include -+#include -+#include "main.h" -+#include "rtw8822c.h" -+#include "usb.h" -+ -+static const struct usb_device_id rtw_8822cu_id_table[] = { -+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc82c, 0xff, 0xff, 0xff), -+ .driver_info = (kernel_ulong_t)&(rtw8822c_hw_spec) }, -+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc812, 0xff, 0xff, 0xff), -+ .driver_info = (kernel_ulong_t)&(rtw8822c_hw_spec) }, -+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc82e, 0xff, 0xff, 0xff), -+ .driver_info = (kernel_ulong_t)&(rtw8822c_hw_spec) }, -+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xd820, 0xff, 0xff, 0xff), -+ .driver_info = (kernel_ulong_t)&(rtw8822c_hw_spec) }, -+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xd82b, 0xff, 0xff, 0xff), -+ .driver_info = (kernel_ulong_t)&(rtw8822c_hw_spec) }, -+ { USB_DEVICE_AND_INTERFACE_INFO(0x13b1, 0x0043, 0xff, 0xff, 0xff), -+ .driver_info = (kernel_ulong_t)&(rtw8822c_hw_spec) }, /* Alpha - Alpha */ -+ {}, -+}; -+MODULE_DEVICE_TABLE(usb, rtw_8822cu_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_8822cu_driver = { -+ .name = "rtw_8822cu", -+ .id_table = rtw_8822cu_id_table, -+ .probe = rtw8822bu_probe, -+ .disconnect = rtw_usb_disconnect, -+}; -+module_usb_driver(rtw_8822cu_driver); -+ -+MODULE_AUTHOR("Realtek Corporation"); -+MODULE_DESCRIPTION("Realtek 802.11ac wireless 8822cu driver"); -+MODULE_LICENSE("Dual BSD/GPL"); --- -cgit - -From 87caeef032fc3921bc866ad7becb6ed51aa8b27b Mon Sep 17 00:00:00 2001 -From: Sascha Hauer -Date: Fri, 2 Dec 2022 09:12:24 +0100 -Subject: wifi: 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 -Signed-off-by: Kalle Valo -Link: https://lore.kernel.org/r/20221202081224.2779981-12-s.hauer@pengutronix.de ---- - 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 +++++++++- - drivers/net/wireless/realtek/rtw88/rtw8723du.c | 36 ++++++++++++++++++++++++++ - 5 files changed, 90 insertions(+), 1 deletion(-) - create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8723du.c - -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 fe2dd90204a78..fe7293ee87b45 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..322a805da76b0 ---- /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 -+#include -+#include "main.h" -+#include "rtw8723d.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 */ -+ { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xd611, 0xff, 0xff, 0xff), -+ .driver_info = (kernel_ulong_t)&(rtw8723d_hw_spec) }, /* Edimax EW-7611ULB V2 */ -+ { }, -+}; -+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 "); -+MODULE_DESCRIPTION("Realtek 802.11n wireless 8723du driver"); -+MODULE_LICENSE("Dual BSD/GPL"); --- -cgit -