From 09c81d92740f9e0143a3b2e9fe1dcefc20ded3bd Mon Sep 17 00:00:00 2001 From: AmadeusGhost <42570690+AmadeusGhost@users.noreply.github.com> Date: Thu, 8 Sep 2022 23:03:15 +0800 Subject: [PATCH] rtw88: move usb part out of backport tree Create a useless driver to avoid affecting the backport tree. --- ...ilter_config-with-rtwdev--mutex-held.patch | 12 - .../rtl/004-rtw88-Drop-coex-mutex.patch | 60 - ...06-rtw88-Add-common-USB-chip-support.patch | 1283 ----------------- ...-rtw88-Add-rtw8821cu-chipset-support.patch | 198 --- ...able-powersave-modes-for-USB-devices.patch | 12 - package/kernel/mac80211/realtek.mk | 15 +- package/kernel/rtw88-usb/Makefile | 132 ++ .../patches/001-sync-upstream-regd.patch | 391 +++++ .../patches/002-drop-rf_lock.patch} | 47 +- .../patches/003-drop-h2c-lock.patch} | 48 +- .../patches/004-drop-coex-mutex.patch | 74 + ...te-over-vif-sta-list-non-atomically.patch} | 45 +- .../patches/100-update-makefile.patch | 25 + .../rtw88-usb/patches/101-wireless-5.14.patch | 14 + 14 files changed, 736 insertions(+), 1620 deletions(-) delete mode 100644 package/kernel/mac80211/patches/rtl/001-rtw88-Call-rtw_fw_beacon_filter_config-with-rtwdev--mutex-held.patch delete mode 100644 package/kernel/mac80211/patches/rtl/004-rtw88-Drop-coex-mutex.patch delete mode 100644 package/kernel/mac80211/patches/rtl/006-rtw88-Add-common-USB-chip-support.patch delete mode 100644 package/kernel/mac80211/patches/rtl/007-rtw88-Add-rtw8821cu-chipset-support.patch delete mode 100644 package/kernel/mac80211/patches/rtl/010-rtw88-disable-powersave-modes-for-USB-devices.patch create mode 100644 package/kernel/rtw88-usb/Makefile create mode 100644 package/kernel/rtw88-usb/patches/001-sync-upstream-regd.patch rename package/kernel/{mac80211/patches/rtl/002-rtw88-Drop-rf_lock.patch => rtw88-usb/patches/002-drop-rf_lock.patch} (65%) rename package/kernel/{mac80211/patches/rtl/003-rtw88-Drop-h2c.lock.patch => rtw88-usb/patches/003-drop-h2c-lock.patch} (54%) create mode 100644 package/kernel/rtw88-usb/patches/004-drop-coex-mutex.patch rename package/kernel/{mac80211/patches/rtl/005-rtw88-iterate-over-vif-sta-list-non-atomically.patch => rtw88-usb/patches/005-iterate-over-vif-sta-list-non-atomically.patch} (78%) create mode 100644 package/kernel/rtw88-usb/patches/100-update-makefile.patch create mode 100644 package/kernel/rtw88-usb/patches/101-wireless-5.14.patch diff --git a/package/kernel/mac80211/patches/rtl/001-rtw88-Call-rtw_fw_beacon_filter_config-with-rtwdev--mutex-held.patch b/package/kernel/mac80211/patches/rtl/001-rtw88-Call-rtw_fw_beacon_filter_config-with-rtwdev--mutex-held.patch deleted file mode 100644 index f33033715..000000000 --- a/package/kernel/mac80211/patches/rtl/001-rtw88-Call-rtw_fw_beacon_filter_config-with-rtwdev--mutex-held.patch +++ /dev/null @@ -1,12 +0,0 @@ ---- a/drivers/net/wireless/realtek/rtw88/mac80211.c -+++ b/drivers/net/wireless/realtek/rtw88/mac80211.c -@@ -455,8 +455,8 @@ static int rtw_ops_sta_remove(struct iee - { - 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); - diff --git a/package/kernel/mac80211/patches/rtl/004-rtw88-Drop-coex-mutex.patch b/package/kernel/mac80211/patches/rtl/004-rtw88-Drop-coex-mutex.patch deleted file mode 100644 index 98a2f8fb2..000000000 --- a/package/kernel/mac80211/patches/rtl/004-rtw88-Drop-coex-mutex.patch +++ /dev/null @@ -1,60 +0,0 @@ ---- a/drivers/net/wireless/realtek/rtw88/coex.c -+++ b/drivers/net/wireless/realtek/rtw88/coex.c -@@ -606,7 +606,7 @@ static struct sk_buff *rtw_coex_info_req - 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); - -@@ -623,7 +623,6 @@ static struct sk_buff *rtw_coex_info_req - } - - out: -- mutex_unlock(&coex->mutex); - return skb_resp; - } - ---- a/drivers/net/wireless/realtek/rtw88/debug.c -+++ b/drivers/net/wireless/realtek/rtw88/debug.c -@@ -794,7 +794,9 @@ static int rtw_debugfs_get_coex_info(str - 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; - } ---- a/drivers/net/wireless/realtek/rtw88/main.c -+++ b/drivers/net/wireless/realtek/rtw88/main.c -@@ -1843,7 +1843,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); -@@ -1910,7 +1909,6 @@ void rtw_core_deinit(struct rtw_dev *rtw - } - - mutex_destroy(&rtwdev->mutex); -- mutex_destroy(&rtwdev->coex.mutex); - mutex_destroy(&rtwdev->hal.tx_power_mutex); - } - EXPORT_SYMBOL(rtw_core_deinit); ---- a/drivers/net/wireless/realtek/rtw88/main.h -+++ b/drivers/net/wireless/realtek/rtw88/main.h -@@ -1429,8 +1429,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; - diff --git a/package/kernel/mac80211/patches/rtl/006-rtw88-Add-common-USB-chip-support.patch b/package/kernel/mac80211/patches/rtl/006-rtw88-Add-common-USB-chip-support.patch deleted file mode 100644 index 1625b7d3b..000000000 --- a/package/kernel/mac80211/patches/rtl/006-rtw88-Add-common-USB-chip-support.patch +++ /dev/null @@ -1,1283 +0,0 @@ ---- a/drivers/net/wireless/realtek/rtw88/Kconfig -+++ b/drivers/net/wireless/realtek/rtw88/Kconfig -@@ -19,6 +19,10 @@ config RTW88_PCI - tristate - depends on m - -+config RTW88_USB -+ tristate -+ depends on m -+ - config RTW88_8822B - tristate - depends on m ---- a/drivers/net/wireless/realtek/rtw88/Makefile -+++ b/drivers/net/wireless/realtek/rtw88/Makefile -@@ -45,3 +45,6 @@ rtw88_8821ce-objs := rtw8821ce.o - - obj-$(CPTCFG_RTW88_PCI) += rtw88_pci.o - rtw88_pci-objs := pci.o -+ -+obj-$(CPTCFG_RTW88_USB) += rtw88_usb.o -+rtw88_usb-objs := usb.o ---- 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 rt - 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; - } - ---- a/drivers/net/wireless/realtek/rtw88/main.c -+++ b/drivers/net/wireless/realtek/rtw88/main.c -@@ -1561,6 +1561,10 @@ static int rtw_chip_parameter_setup(stru - 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; ---- a/drivers/net/wireless/realtek/rtw88/main.h -+++ b/drivers/net/wireless/realtek/rtw88/main.h -@@ -845,6 +845,10 @@ struct rtw_chip_ops { - enum rtw_bb_path tx_path_1ss, - enum rtw_bb_path tx_path_cck, - 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); ---- 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) \ ---- a/drivers/net/wireless/realtek/rtw88/tx.h -+++ b/drivers/net/wireless/realtek/rtw88/tx.h -@@ -67,6 +67,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, -@@ -119,4 +127,27 @@ rtw_tx_write_data_h2c_get(struct rtw_dev - 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) -+{ -+ struct rtw_chip_info *chip = rtwdev->chip; -+ -+ chip->ops->fill_txdesc_checksum(rtwdev, pkt_info, txdesc); -+} -+ - #endif ---- /dev/null -+++ b/drivers/net/wireless/realtek/rtw88/usb.c -@@ -0,0 +1,1037 @@ -+// 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 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 void usbctrl_async_callback(struct urb *urb) -+{ -+ /* free dr */ -+ kfree(urb->setup_packet); -+ /* free databuf */ -+ kfree(urb->transfer_buffer); -+} -+ -+static int usbctrl_vendorreq_async_write(struct usb_device *udev, u8 request, -+ u16 value, u16 index, void *pdata, -+ u16 len) -+{ -+ const u16 databuf_maxlen = RTW_USB_VENQT_MAX_BUF_SIZE; -+ struct usb_ctrlrequest *dr; -+ unsigned int pipe; -+ struct urb *urb; -+ u8 *databuf; -+ u8 reqtype; -+ int ret; -+ -+ if (WARN_ON_ONCE(len > databuf_maxlen)) -+ len = databuf_maxlen; -+ -+ pipe = usb_sndctrlpipe(udev, 0); /* write_out */ -+ reqtype = RTW_USB_CMD_WRITE; -+ -+ dr = kzalloc(sizeof(*dr), GFP_ATOMIC); -+ if (!dr) -+ return -ENOMEM; -+ -+ databuf = kmemdup(pdata, len, GFP_ATOMIC); -+ if (!databuf) { -+ kfree(dr); -+ return -ENOMEM; -+ } -+ -+ urb = usb_alloc_urb(0, GFP_ATOMIC); -+ if (!urb) { -+ kfree(databuf); -+ kfree(dr); -+ return -ENOMEM; -+ } -+ -+ dr->bRequestType = reqtype; -+ dr->bRequest = request; -+ dr->wValue = cpu_to_le16(value); -+ dr->wIndex = cpu_to_le16(index); -+ dr->wLength = cpu_to_le16(len); -+ -+ usb_fill_control_urb(urb, udev, pipe, -+ (unsigned char *)dr, databuf, len, -+ usbctrl_async_callback, NULL); -+ ret = usb_submit_urb(urb, GFP_ATOMIC); -+ if (ret < 0) { -+ kfree(databuf); -+ kfree(dr); -+ } -+ -+ usb_free_urb(urb); -+ -+ return ret; -+} -+ -+static u32 rtw_usb_read_sync(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); -+ -+ if (++rtwusb->usb_data_index >= RTW_USB_MAX_RX_COUNT) -+ rtwusb->usb_data_index = 0; -+ data = &rtwusb->usb_data[rtwusb->usb_data_index]; -+ -+ spin_unlock_irqrestore(&rtwusb->usb_lock, flags); -+ -+ 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, "reg 0x%x, usbctrl_vendorreq failed with %d\n", -+ addr, ret); -+ -+ return le32_to_cpu(*data); -+} -+ -+static u8 rtw_usb_read8_sync(struct rtw_dev *rtwdev, u32 addr) -+{ -+ return (u8)rtw_usb_read_sync(rtwdev, addr, 1); -+} -+ -+static u16 rtw_usb_read16_sync(struct rtw_dev *rtwdev, u32 addr) -+{ -+ return (u16)rtw_usb_read_sync(rtwdev, addr, 2); -+} -+ -+static u32 rtw_usb_read32_sync(struct rtw_dev *rtwdev, u32 addr) -+{ -+ return (u32)rtw_usb_read_sync(rtwdev, addr, 4); -+} -+ -+static void rtw_usb_write_async(struct rtw_dev *rtwdev, u32 addr, u32 val, -+ u16 len) -+{ -+ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); -+ struct usb_device *udev = rtwusb->udev; -+ u8 request; -+ u16 wvalue; -+ u16 index; -+ __le32 data; -+ -+ request = RTW_USB_CMD_REQ; -+ index = RTW_USB_VENQT_CMD_IDX; /* n/a */ -+ wvalue = (u16)(addr & 0x0000ffff); -+ data = cpu_to_le32(val); -+ usbctrl_vendorreq_async_write(udev, request, wvalue, index, &data, len); -+} -+ -+static void rtw_usb_write8_async(struct rtw_dev *rtwdev, u32 addr, u8 val) -+{ -+ rtw_usb_write_async(rtwdev, addr, val, 1); -+} -+ -+static void rtw_usb_write16_async(struct rtw_dev *rtwdev, u32 addr, u16 val) -+{ -+ rtw_usb_write_async(rtwdev, addr, val, 2); -+} -+ -+static void rtw_usb_write32_async(struct rtw_dev *rtwdev, u32 addr, u32 val) -+{ -+ rtw_usb_write_async(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] = 1; -+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID7] = 1; -+ 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_txcb_enqueue(struct rtw_usb_txcb *txcb, struct sk_buff *skb) -+{ -+ skb_queue_tail(&txcb->tx_ack_queue, skb); -+} -+ -+static void rtw_usb_tx_agg_skb(struct rtw_usb *rtwusb, struct sk_buff_head *list, -+ struct sk_buff *skb_head, struct sk_buff *skb, -+ struct rtw_usb_txcb *txcb) -+{ -+ struct sk_buff *skb_iter; -+ unsigned long flags; -+ u8 *data_ptr; -+ int agg_num = 0, len, max_len; -+ -+ data_ptr = skb_head->data; -+ skb_iter = skb; -+ -+ while (skb_iter) { -+ memcpy(data_ptr, skb_iter->data, skb_iter->len); -+ len = ALIGN(skb_iter->len, 8); -+ skb_put(skb_head, len); -+ data_ptr += len; -+ agg_num++; -+ -+ rtw_usb_txcb_enqueue(txcb, skb_iter); -+ -+ spin_lock_irqsave(&list->lock, flags); -+ -+ skb_iter = skb_peek(list); -+ max_len = RTW_USB_MAX_XMITBUF_SZ - skb_head->len; -+ -+ if (skb_iter && skb_iter->len < max_len) -+ __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); -+} -+ -+static void rtw_usb_indicate_tx_status(struct rtw_dev *rtwdev, -+ struct sk_buff *skb) -+{ -+ struct ieee80211_hw *hw = rtwdev->hw; -+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); -+ struct rtw_usb_tx_data *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); -+ return; -+ } -+ -+ /* 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); -+} -+ -+static void rtw_usb_write_port_tx_complete(struct urb *urb) -+{ -+ struct rtw_usb_txcb *txcb = urb->context; -+ struct rtw_dev *rtwdev = txcb->rtwdev; -+ -+ while (true) { -+ struct sk_buff *skb = skb_dequeue(&txcb->tx_ack_queue); -+ -+ if (!skb) -+ break; -+ -+ if (GET_TX_DESC_QSEL(skb->data) <= TX_DESC_QSEL_TID7) -+ rtw_usb_indicate_tx_status(rtwdev, skb); -+ else -+ dev_kfree_skb_any(skb); -+ } -+ -+ kfree(txcb); -+} -+ -+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 = rtwusb->qsel_to_ep[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 struct sk_buff *rtw_usb_tx_agg_check(struct rtw_usb *rtwusb, -+ struct sk_buff *skb, -+ int index, -+ struct rtw_usb_txcb *txcb) -+{ -+ struct sk_buff_head *list; -+ struct sk_buff *skb_head; -+ -+ list = &rtwusb->tx_queue[index]; -+ if (skb_queue_empty(list)) -+ return NULL; -+ -+ skb_head = dev_alloc_skb(RTW_USB_MAX_XMITBUF_SZ); -+ if (!skb_head) -+ return NULL; -+ -+ rtw_usb_tx_agg_skb(rtwusb, list, skb_head, skb, txcb); -+ -+ return skb_head; -+} -+ -+static void rtw_usb_tx_agg(struct rtw_usb *rtwusb, struct sk_buff *skb, int index) -+{ -+ struct rtw_dev *rtwdev = rtwusb->rtwdev; -+ struct sk_buff *skb_head; -+ struct rtw_usb_txcb *txcb; -+ u8 qsel; -+ -+ txcb = kmalloc(sizeof(*txcb), GFP_ATOMIC); -+ if (!txcb) -+ return; -+ -+ txcb->rtwdev = rtwdev; -+ skb_queue_head_init(&txcb->tx_ack_queue); -+ -+ skb_head = rtw_usb_tx_agg_check(rtwusb, skb, index, txcb); -+ if (!skb_head) { -+ skb_head = skb; -+ rtw_usb_txcb_enqueue(txcb, skb); -+ } -+ -+ qsel = GET_TX_DESC_QSEL(skb->data); -+ -+ rtw_usb_write_port(rtwdev, qsel, skb_head, -+ rtw_usb_write_port_tx_complete, txcb); -+ -+ if (skb_head != skb) -+ dev_kfree_skb(skb_head); -+} -+ -+static void rtw_usb_tx_handler(struct work_struct *work) -+{ -+ struct rtw_usb *rtwusb = container_of(work, struct rtw_usb, tx_work); -+ struct sk_buff *skb; -+ int index, limit; -+ -+ for (index = ARRAY_SIZE(rtwusb->tx_queue) - 1; index >= 0; index--) { -+ for (limit = 0; limit < 200; limit++) { -+ skb = skb_dequeue(&rtwusb->tx_queue[index]); -+ if (skb) -+ rtw_usb_tx_agg(rtwusb, skb, index); -+ else -+ 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) -+{ -+ 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) -+{ -+ 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); -+ if (unlikely(!rtwusb)) -+ return -EINVAL; -+ -+ 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); -+ 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 = rtwusb->qsel_to_ep[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; -+ 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_rx_data_put(struct rtw_usb *rtwusb, -+ struct rx_usb_ctrl_block *rxcb) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&rtwusb->rx_data_list_lock, flags); -+ list_move(&rxcb->list, &rtwusb->rx_data_free); -+ spin_unlock_irqrestore(&rtwusb->rx_data_list_lock, flags); -+} -+ -+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_data_put(rtwusb, rxcb); -+ if (rtwusb->running) -+ queue_work(rtwusb->rxwq, &rtwusb->rx_refill_work); -+ } 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 unknown=%d\n", urb->status); -+ break; -+ } -+ if (skb) -+ dev_kfree_skb_any(skb); -+ } -+} -+ -+static void rtw_usb_rx_refill_work(struct work_struct *work) -+{ -+ struct rtw_usb *rtwusb = container_of(work, struct rtw_usb, rx_refill_work); -+ struct rtw_dev *rtwdev = rtwusb->rtwdev; -+ struct rx_usb_ctrl_block *rxcb; -+ unsigned long flags; -+ int error, limit; -+ -+ for (limit = 0; limit < 200; limit++) { -+ spin_lock_irqsave(&rtwusb->rx_data_list_lock, flags); -+ -+ rxcb = list_first_entry_or_null(&rtwusb->rx_data_free, -+ struct rx_usb_ctrl_block, list); -+ -+ spin_unlock_irqrestore(&rtwusb->rx_data_list_lock, flags); -+ if (!rxcb) -+ return; -+ -+ rxcb->rx_skb = alloc_skb(RTW_USB_MAX_RECVBUF_SZ, GFP_KERNEL); -+ 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); -+ -+ spin_lock_irqsave(&rtwusb->rx_data_list_lock, flags); -+ list_move(&rxcb->list, &rtwusb->rx_data_used); -+ spin_unlock_irqrestore(&rtwusb->rx_data_list_lock, flags); -+ -+ error = usb_submit_urb(rxcb->rx_urb, GFP_KERNEL); -+ if (error) { -+ kfree_skb(rxcb->rx_skb); -+ if (error != -ENODEV) -+ rtw_err(rtwdev, "Err sending rx data urb %d\n", -+ error); -+ rtw_usb_rx_data_put(rtwusb, rxcb); -+ -+ return; -+ } -+ } -+} -+ -+static void rtw_usb_cancel_rx_bufs(struct rtw_usb *rtwusb) -+{ -+ struct rx_usb_ctrl_block *rxcb; -+ -+ rtwusb->running = 0; -+ cancel_work_sync(&rtwusb->rx_refill_work); -+ -+ while (true) { -+ unsigned long flags; -+ -+ spin_lock_irqsave(&rtwusb->rx_data_list_lock, flags); -+ -+ rxcb = list_first_entry_or_null(&rtwusb->rx_data_used, -+ struct rx_usb_ctrl_block, list); -+ if (rxcb) -+ list_move(&rxcb->list, &rtwusb->rx_data_free); -+ -+ spin_unlock_irqrestore(&rtwusb->rx_data_list_lock, flags); -+ -+ if (!rxcb) -+ break; -+ -+ usb_kill_urb(rxcb->rx_urb); -+ } -+} -+ -+static void rtw_usb_free_rx_bufs(struct rtw_usb *rtwusb) -+{ -+ struct rx_usb_ctrl_block *rxcb; -+ -+ list_for_each_entry(rxcb, &rtwusb->rx_data_free, list) -+ 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->rtwdev = rtwusb->rtwdev; -+ rxcb->rx_urb = usb_alloc_urb(0, GFP_KERNEL); -+ if (!rxcb->rx_urb) -+ goto err; -+ list_add_tail(&rxcb->list, &rtwusb->rx_data_free); -+ } -+ -+ 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) -+{ -+ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); -+ -+ rtwusb->running = 1; -+ queue_work(rtwusb->rxwq, &rtwusb->rx_refill_work); -+ -+ return 0; -+} -+ -+static void rtw_usb_stop(struct rtw_dev *rtwdev) -+{ -+ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); -+ -+ rtw_usb_cancel_rx_bufs(rtwusb); -+} -+ -+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_async, -+ .write16 = rtw_usb_write16_async, -+ .write32 = rtw_usb_write32_async, -+ .read8 = rtw_usb_read8_sync, -+ .read16 = rtw_usb_read16_sync, -+ .read32 = rtw_usb_read32_sync, -+ -+ .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); -+ -+ 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); -+ -+ 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_RX_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; -+ -+ INIT_WORK(&rtwusb->rx_refill_work, rtw_usb_rx_refill_work); -+ INIT_LIST_HEAD(&rtwusb->rx_data_free); -+ INIT_LIST_HEAD(&rtwusb->rx_data_used); -+ spin_lock_init(&rtwusb->rx_data_list_lock); -+ -+ 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"); ---- /dev/null -+++ b/drivers/net/wireless/realtek/rtw88/usb.h -@@ -0,0 +1,114 @@ -+/* 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_RX_COUNT 100 -+#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 (1592 * 3) -+#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; -+ struct list_head list; -+}; -+ -+struct rtw_usb_tx_data { -+ u8 sn; -+}; -+ -+struct rtw_usb { -+ struct rtw_dev *rtwdev; -+ struct usb_device *udev; -+ -+ /* protects rx_data_free and rx_data_used lists */ -+ spinlock_t rx_data_list_lock; -+ bool running; -+ struct work_struct rx_refill_work; -+ struct list_head rx_data_free; -+ struct list_head rx_data_used; -+ -+ /* protects usb_data_index */ -+ spinlock_t usb_lock; -+ __le32 *usb_data; -+ 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 ---- a/drivers/net/wireless/realtek/rtw88/util.c -+++ b/drivers/net/wireless/realtek/rtw88/util.c -@@ -167,7 +167,7 @@ struct rtw_iter_vifs_data { - struct list_head list; - }; - --void rtw_collect_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) -+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; diff --git a/package/kernel/mac80211/patches/rtl/007-rtw88-Add-rtw8821cu-chipset-support.patch b/package/kernel/mac80211/patches/rtl/007-rtw88-Add-rtw8821cu-chipset-support.patch deleted file mode 100644 index 05ab6798c..000000000 --- a/package/kernel/mac80211/patches/rtl/007-rtw88-Add-rtw8821cu-chipset-support.patch +++ /dev/null @@ -1,198 +0,0 @@ ---- a/drivers/net/wireless/realtek/rtw88/Kconfig -+++ b/drivers/net/wireless/realtek/rtw88/Kconfig -@@ -87,6 +87,18 @@ config RTW88_8821CE - - 802.11ac PCIe wireless network adapter - -+config RTW88_8821CU -+ tristate "Realtek 8821CU USB wireless network adapter" -+ depends on m -+ 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 ---- a/drivers/net/wireless/realtek/rtw88/Makefile -+++ b/drivers/net/wireless/realtek/rtw88/Makefile -@@ -43,6 +43,9 @@ rtw88_8821c-objs := rtw8821c.o rtw8821c - obj-$(CPTCFG_RTW88_8821CE) += rtw88_8821ce.o - rtw88_8821ce-objs := rtw8821ce.o - -+obj-$(CPTCFG_RTW88_8821CU) += rtw88_8821cu.o -+rtw88_8821cu-objs := rtw8821cu.o -+ - obj-$(CPTCFG_RTW88_PCI) += rtw88_pci.o - rtw88_pci-objs := pci.o - ---- 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(stru - 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, -@@ -65,6 +71,9 @@ static int rtw8821c_read_efuse(struct rt - 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; -@@ -1128,6 +1137,18 @@ static void rtw8821c_phy_cck_pd_set(stru - 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) -+{ -+ 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 struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8821c[] = { - {0x0086, - RTW_PWR_CUT_ALL_MSK, -@@ -1499,6 +1520,9 @@ static const struct rtw_intf_phy_para_ta - static const struct rtw_rfe_def rtw8821c_rfe_defs[] = { - [0] = RTW_DEF_RFE(8821c, 0, 0), - [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[] = { -@@ -1573,6 +1597,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, ---- 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; - }; - }; - ---- /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 "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 "); -+MODULE_DESCRIPTION("Realtek 802.11ac wireless 8821cu driver"); -+MODULE_LICENSE("Dual BSD/GPL"); ---- /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 diff --git a/package/kernel/mac80211/patches/rtl/010-rtw88-disable-powersave-modes-for-USB-devices.patch b/package/kernel/mac80211/patches/rtl/010-rtw88-disable-powersave-modes-for-USB-devices.patch deleted file mode 100644 index 673d1f5d2..000000000 --- a/package/kernel/mac80211/patches/rtl/010-rtw88-disable-powersave-modes-for-USB-devices.patch +++ /dev/null @@ -1,12 +0,0 @@ ---- a/drivers/net/wireless/realtek/rtw88/mac80211.c -+++ b/drivers/net/wireless/realtek/rtw88/mac80211.c -@@ -85,7 +85,8 @@ static int rtw_ops_config(struct ieee802 - } - - if (changed & IEEE80211_CONF_CHANGE_PS) { -- if (hw->conf.flags & IEEE80211_CONF_PS) { -+ if (hw->conf.flags & IEEE80211_CONF_PS && -+ rtw_hci_type(rtwdev) != RTW_HCI_TYPE_USB) { - rtwdev->ps_enabled = true; - } else { - rtwdev->ps_enabled = false; diff --git a/package/kernel/mac80211/realtek.mk b/package/kernel/mac80211/realtek.mk index 1db4c8ac2..44c6c25b0 100644 --- a/package/kernel/mac80211/realtek.mk +++ b/package/kernel/mac80211/realtek.mk @@ -25,8 +25,8 @@ config-y += RTL8XXXU_UNTESTED config-$(call config_package,rtl8723bs) += RTL8723BS config-y += STAGING -config-$(call config_package,rtw88) += RTW88 RTW88_CORE RTW88_PCI RTW88_USB -config-y += RTW88_8821CU RTW88_8822BE RTW88_8822CE RTW88_8723DE +config-$(call config_package,rtw88) += RTW88 RTW88_CORE RTW88_PCI +config-y += RTW88_8822BE RTW88_8822CE RTW88_8723DE config-$(CONFIG_PACKAGE_RTW88_DEBUG) += RTW88_DEBUG config-$(CONFIG_PACKAGE_RTW88_DEBUGFS) += RTW88_DEBUGFS @@ -195,11 +195,9 @@ endef define KernelPackage/rtw88 $(call KernelPackage/mac80211/Default) - TITLE:=Realtek RTL8821CU/RTL8822BE/RTL8822CE/RTL8723DE - DEPENDS+= @(PCI_SUPPORT||USB_SUPPORT) +kmod-mac80211 +@DRIVER_11AC_SUPPORT +@DRIVER_11N_SUPPORT + TITLE:=Realtek RTL8822BE/RTL8822CE/RTL8723DE + DEPENDS+= @(PCI_SUPPORT) +kmod-mac80211 +@DRIVER_11AC_SUPPORT +@DRIVER_11N_SUPPORT FILES:=\ - $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8821c.ko \ - $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8821cu.ko \ $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8822be.ko \ $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8822b.ko \ $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8822ce.ko \ @@ -207,9 +205,8 @@ define KernelPackage/rtw88 $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8723de.ko \ $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_8723d.ko \ $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_core.ko \ - $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_pci.ko \ - $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_usb.ko - AUTOLOAD:=$(call AutoProbe,rtw88_8821cu rtw88_8822be rtw88_8822ce rtw88_8723de) + $(PKG_BUILD_DIR)/drivers/net/wireless/realtek/rtw88/rtw88_pci.ko + AUTOLOAD:=$(call AutoProbe,rtw88_8822be rtw88_8822ce rtw88_8723de) endef define KernelPackage/rtl8723bs diff --git a/package/kernel/rtw88-usb/Makefile b/package/kernel/rtw88-usb/Makefile new file mode 100644 index 000000000..10536b6b4 --- /dev/null +++ b/package/kernel/rtw88-usb/Makefile @@ -0,0 +1,132 @@ +# +# Copyright (C) 2017 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=rtw88-usb +PKG_RELEASE:=1 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_DATE:=2021-07-06 +PKG_SOURCE_URL:=https://github.com/ulli-kroll/rtw88-usb.git +PKG_SOURCE_VERSION:=dd05eec8e5ac934b3d8e67e8008228f842b4ce1c +PKG_MIRROR_HASH:=9932f69573a3469d1eba403c7964a9472530fcfa1c29356babeecdad8d9c6991 + +PKG_BUILD_PARALLEL:=1 +PKG_LICENSE:=GPL-2.0 +PKG_LICENSE_FILES:=LICENSE + +STAMP_CONFIGURED_DEPENDS := $(STAGING_DIR)/usr/include/mac80211-backport/backport/autoconf.h + +include $(INCLUDE_DIR)/kernel.mk +include $(INCLUDE_DIR)/package.mk + +define KernelPackage/rtw88-default + SUBMENU:=Wireless Drivers + TITLE:=Realtek rtw88 family usb driver + DEPENDS:=+kmod-mac80211 +kmod-usb-core \ + +@DRIVER_11N_SUPPORT +@DRIVER_11AC_SUPPORT +endef + +define KernelPackage/rtw88-usb + $(KernelPackage/rtw88-default) + HIDDEN:=1 + FILES:= \ + $(PKG_BUILD_DIR)/rtw88_usb.ko \ + $(PKG_BUILD_DIR)/rtw88_core.ko +endef + +define KernelPackage/rtl8723du + $(KernelPackage/rtw88-default) + TITLE:=Realtek RTL8723DU support + DEPENDS+=+kmod-rtw88-usb +rtl8723du-firmware + FILES:= \ + $(PKG_BUILD_DIR)/rtw88_8723d.ko \ + $(PKG_BUILD_DIR)/rtw88_8723du.ko + AUTOLOAD:=$(call AutoProbe,rtw88_8723du) +endef + +define KernelPackage/rtl8821cu + $(KernelPackage/rtw88-default) + TITLE:=Realtek RTL8821CU support + DEPENDS+=+kmod-rtw88-usb +rtl8821ce-firmware + FILES:= \ + $(PKG_BUILD_DIR)/rtw88_8821c.ko \ + $(PKG_BUILD_DIR)/rtw88_8821cu.ko + AUTOLOAD:=$(call AutoProbe,rtw88_8821cu) +endef + +define KernelPackage/rtl8822bu + $(KernelPackage/rtw88-default) + TITLE:=Realtek RTL8822BU support + DEPENDS+=+kmod-rtw88-usb +rtl8822be-firmware + FILES:= \ + $(PKG_BUILD_DIR)/rtw88_8822b.ko \ + $(PKG_BUILD_DIR)/rtw88_8822bu.ko + AUTOLOAD:=$(call AutoProbe,rtw88_8822bu) +endef + +define KernelPackage/rtl8822cu + $(KernelPackage/rtw88-default) + TITLE:=Realtek RTL8822CU support + DEPENDS+=+kmod-rtw88-usb +rtl8822ce-firmware + FILES:= \ + $(PKG_BUILD_DIR)/rtw88_8822c.ko \ + $(PKG_BUILD_DIR)/rtw88_8822cu.ko + AUTOLOAD:=$(call AutoProbe,rtw88_8822cu) +endef + +NOSTDINC_FLAGS := \ + $(KERNEL_NOSTDINC_FLAGS) \ + -I$(PKG_BUILD_DIR) \ + -I$(STAGING_DIR)/usr/include/mac80211-backport/uapi \ + -I$(STAGING_DIR)/usr/include/mac80211-backport \ + -I$(STAGING_DIR)/usr/include/mac80211/uapi \ + -I$(STAGING_DIR)/usr/include/mac80211 \ + -include backport/autoconf.h \ + -include backport/backport.h + +ifdef CONFIG_PACKAGE_kmod-rtw88-usb +PKG_MAKE_FLAGS += \ + CONFIG_RTW88_USB=m \ + CONFIG_RTW88_CORE=m +endif +ifdef CONFIG_PACKAGE_kmod-rtl8723du + PKG_MAKE_FLAGS += \ + CONFIG_RTW88_8723D=m \ + CONFIG_RTW88_8723DU=m +endif +ifdef CONFIG_PACKAGE_kmod-rtl8821cu + PKG_MAKE_FLAGS += \ + CONFIG_RTW88_8821C=m \ + CONFIG_RTW88_8821CU=m +endif +ifdef CONFIG_PACKAGE_kmod-rtl8822bu + PKG_MAKE_FLAGS += \ + CONFIG_RTW88_8822B=m \ + CONFIG_RTW88_8822BU=m +endif +ifdef CONFIG_PACKAGE_kmod-rtl8822cu + PKG_MAKE_FLAGS += \ + CONFIG_RTW88_8822C=m \ + CONFIG_RTW88_8822CU=m +endif + +define Build/Compile + +$(MAKE) $(PKG_JOBS) -C "$(LINUX_DIR)" \ + $(KERNEL_MAKE_FLAGS) \ + $(PKG_MAKE_FLAGS) \ + M="$(PKG_BUILD_DIR)" \ + NOSTDINC_FLAGS="$(NOSTDINC_FLAGS)" \ + modules +endef + +$(eval $(call KernelPackage,rtw88-usb)) +$(eval $(call KernelPackage,rtl8723du)) +$(eval $(call KernelPackage,rtl8821cu)) +$(eval $(call KernelPackage,rtl8822bu)) +$(eval $(call KernelPackage,rtl8822cu)) diff --git a/package/kernel/rtw88-usb/patches/001-sync-upstream-regd.patch b/package/kernel/rtw88-usb/patches/001-sync-upstream-regd.patch new file mode 100644 index 000000000..8b4843088 --- /dev/null +++ b/package/kernel/rtw88-usb/patches/001-sync-upstream-regd.patch @@ -0,0 +1,391 @@ +--- a/debug.c ++++ b/debug.c +@@ -868,37 +868,6 @@ static int rtw_debugfs_get_coex_enable(struct seq_file *m, void *v) + return 0; + } + +-static ssize_t rtw_debugfs_set_edcca_enable(struct file *filp, +- const char __user *buffer, +- size_t count, loff_t *loff) +-{ +- struct seq_file *seqpriv = (struct seq_file *)filp->private_data; +- struct rtw_debugfs_priv *debugfs_priv = seqpriv->private; +- struct rtw_dev *rtwdev = debugfs_priv->rtwdev; +- char tmp[32 + 1]; +- int err; +- +- rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1); +- +- err = kstrtobool(tmp, &rtw_edcca_enabled); +- if (err) +- return err; +- rtw_phy_adaptivity_set_mode(rtwdev); +- +- return count; +-} +- +-static int rtw_debugfs_get_edcca_enable(struct seq_file *m, void *v) +-{ +- struct rtw_debugfs_priv *debugfs_priv = m->private; +- struct rtw_dev *rtwdev = debugfs_priv->rtwdev; +- struct rtw_dm_info *dm_info = &rtwdev->dm_info; +- +- seq_printf(m, "EDCCA mode %d\n", dm_info->edcca_mode); +- +- return 0; +-} +- + static ssize_t rtw_debugfs_set_fw_crash(struct file *filp, + const char __user *buffer, + size_t count, loff_t *loff) +@@ -1118,11 +1087,6 @@ static struct rtw_debugfs_priv rtw_debug_priv_coex_info = { + .cb_read = rtw_debugfs_get_coex_info, + }; + +-static struct rtw_debugfs_priv rtw_debug_priv_edcca_enable = { +- .cb_write = rtw_debugfs_set_edcca_enable, +- .cb_read = rtw_debugfs_get_edcca_enable, +-}; +- + static struct rtw_debugfs_priv rtw_debug_priv_fw_crash = { + .cb_write = rtw_debugfs_set_fw_crash, + .cb_read = rtw_debugfs_get_fw_crash, +@@ -1209,7 +1173,6 @@ void rtw_debugfs_init(struct rtw_dev *rtwdev) + rtw_debugfs_add_r(tx_pwr_tbl); + rtw_debugfs_add_rw(fw_crash); + rtw_debugfs_add_rw(dm_cap); +- rtw_debugfs_add_rw(edcca_enable); + } + + #endif /* CONFIG_RTW88_DEBUGFS */ +--- a/phy.c ++++ b/phy.c +@@ -9,7 +9,6 @@ + #include "fw.h" + #include "phy.h" + #include "debug.h" +-#include "regd.h" + + struct phy_cfg_pair { + u32 addr; +@@ -121,58 +120,6 @@ static void rtw_phy_cck_pd_init(struct rtw_dev *rtwdev) + dm_info->cck_fa_avg = CCK_FA_AVG_RESET; + } + +-void rtw_phy_set_edcca_th(struct rtw_dev *rtwdev, u8 l2h, u8 h2l) +-{ +- struct rtw_hw_reg_offset *edcca_th = rtwdev->chip->edcca_th; +- +- rtw_write32_mask(rtwdev, +- edcca_th[EDCCA_TH_L2H_IDX].hw_reg.addr, +- edcca_th[EDCCA_TH_L2H_IDX].hw_reg.mask, +- l2h + edcca_th[EDCCA_TH_L2H_IDX].offset); +- rtw_write32_mask(rtwdev, +- edcca_th[EDCCA_TH_H2L_IDX].hw_reg.addr, +- edcca_th[EDCCA_TH_H2L_IDX].hw_reg.mask, +- h2l + edcca_th[EDCCA_TH_H2L_IDX].offset); +-} +-EXPORT_SYMBOL(rtw_phy_set_edcca_th); +- +-void rtw_phy_adaptivity_set_mode(struct rtw_dev *rtwdev) +-{ +- struct rtw_chip_info *chip = rtwdev->chip; +- struct rtw_dm_info *dm_info = &rtwdev->dm_info; +- +- /* turn off in debugfs for debug usage */ +- if (!rtw_edcca_enabled) { +- dm_info->edcca_mode = RTW_EDCCA_NORMAL; +- rtw_dbg(rtwdev, RTW_DBG_PHY, "EDCCA disabled, cannot be set\n"); +- return; +- } +- +- switch (rtwdev->regd.region) { +- case NL80211_DFS_ETSI: +- dm_info->edcca_mode = RTW_EDCCA_ADAPTIVITY; +- dm_info->l2h_th_ini = chip->l2h_th_ini_ad; +- break; +- case NL80211_DFS_JP: +- dm_info->edcca_mode = RTW_EDCCA_ADAPTIVITY; +- dm_info->l2h_th_ini = chip->l2h_th_ini_cs; +- break; +- default: +- dm_info->edcca_mode = RTW_EDCCA_NORMAL; +- break; +- } +-} +- +-static void rtw_phy_adaptivity_init(struct rtw_dev *rtwdev) +-{ +- struct rtw_chip_info *chip = rtwdev->chip; +- +- rtw_regd_init_dfs_region(rtwdev, rtwdev->regd.region); +- rtw_phy_adaptivity_set_mode(rtwdev); +- if (chip->ops->adaptivity_init) +- chip->ops->adaptivity_init(rtwdev); +-} +- + static void rtw_phy_cfo_init(struct rtw_dev *rtwdev) + { + struct rtw_chip_info *chip = rtwdev->chip; +@@ -202,8 +149,6 @@ void rtw_phy_init(struct rtw_dev *rtwdev) + rtw_phy_cck_pd_init(rtwdev); + + dm_info->iqk.done = false; +- dm_info->iqk.done = false; +- rtw_phy_adaptivity_init(rtwdev); + } + EXPORT_SYMBOL(rtw_phy_init); + +--- a/phy.h ++++ b/phy.h +@@ -61,8 +61,6 @@ void rtw_phy_config_swing_table(struct rtw_dev *rtwdev, + struct rtw_swing_table *swing_table); + void rtw_phy_parsing_cfo(struct rtw_dev *rtwdev, + struct rtw_rx_pkt_stat *pkt_stat); +-void rtw_phy_set_edcca_th(struct rtw_dev *rtwdev, u8 l2h, u8 h2l); +-void rtw_phy_adaptivity_set_mode(struct rtw_dev *rtwdev); + + struct rtw_txpwr_lmt_cfg_pair { + u8 regd; +--- a/regd.c ++++ b/regd.c +@@ -7,18 +7,6 @@ + #include "debug.h" + #include "phy.h" + +-static const struct ieee80211_regdomain rtw88_world_regdom = { +- .n_reg_rules = 5, +- .alpha2 = "99", +- .reg_rules = { +- REG_RULE(2412 - 10, 2462 + 10, 40, 0, 20, 0), +- REG_RULE(2467 - 10, 2484 + 10, 40, 0, 20, NL80211_RRF_NO_IR), +- REG_RULE(5180 - 10, 5240 + 10, 80, 0, 20, NL80211_RRF_NO_IR), +- REG_RULE(5260 - 10, 5700 + 10, 80, 0, 20, +- NL80211_RRF_NO_IR | NL80211_RRF_DFS), +- REG_RULE(5745 - 10, 5825 + 10, 80, 0, 20, NL80211_RRF_NO_IR), +- } +-}; + #define COUNTRY_CHPLAN_ENT(_alpha2, _chplan, _txpwr_regd) \ + {.alpha2 = (_alpha2), \ + .chplan = (_chplan), \ +@@ -351,73 +339,28 @@ static struct rtw_regulatory rtw_regd_find_reg_by_name(char *alpha2) + return rtw_defined_chplan; + } + +-static bool rtw_regd_is_ww(struct rtw_regulatory *reg) +-{ +- if (reg->txpwr_regd == RTW_REGD_WW) +- return true; +- return false; +-} +- +-void rtw_regd_init_dfs_region(struct rtw_dev *rtwdev, +- enum nl80211_dfs_regions curr_region) +-{ +- struct ieee80211_hw *hw = rtwdev->hw; +- const struct ieee80211_regdomain *wiphy_regd = NULL; +- +- if (curr_region != RTW_REGION_INVALID) +- return; +- +- rcu_read_lock(); +- wiphy_regd = rcu_dereference(hw->wiphy->regd); +- if (wiphy_regd) +- rtwdev->regd.region = wiphy_regd->dfs_region; +- rcu_read_unlock(); +-} +- + static int rtw_regd_notifier_apply(struct rtw_dev *rtwdev, + struct wiphy *wiphy, + struct regulatory_request *request) + { +- if (request->initiator == NL80211_REGDOM_SET_BY_DRIVER) +- return -ENOTSUPP; +- if (request->initiator == NL80211_REGDOM_SET_BY_USER && +- !IS_ENABLED(CONFIG_RTW88_REGD_USER_REG_HINTS)) +- return -EPERM; +- if (request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE && +- !rtw_regd_is_ww(&rtwdev->regd)) +- return -EINVAL; +- if (request->initiator == NL80211_REGDOM_SET_BY_CORE && +- !rtwdev->efuse.country_worldwide) { +- rtwdev->regd = +- rtw_regd_find_reg_by_name(rtwdev->efuse.country_code); +- /* return to the efuse setting */ +- rtw_regd_init_dfs_region(rtwdev, RTW_REGION_INVALID); ++ if (request->initiator == NL80211_REGDOM_SET_BY_USER) + return 0; +- } + rtwdev->regd = rtw_regd_find_reg_by_name(request->alpha2); + rtw_regd_apply_world_flags(wiphy, request->initiator); +- rtwdev->regd.region = request->dfs_region; + + return 0; + } + + static int +-rtw_regd_init_wiphy(struct rtw_dev *rtwdev, struct wiphy *wiphy, ++rtw_regd_init_wiphy(struct rtw_regulatory *reg, struct wiphy *wiphy, + void (*reg_notifier)(struct wiphy *wiphy, + struct regulatory_request *request)) + { +- struct rtw_regulatory *reg = &rtwdev->regd; +- + wiphy->reg_notifier = reg_notifier; + +- if (rtw_regd_is_ww(reg)) { +- rtwdev->efuse.country_worldwide = true; +- wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; +- wiphy_apply_custom_regulatory(wiphy, &rtw88_world_regdom); +- } else { +- rtwdev->efuse.country_worldwide = false; +- } +- wiphy->regulatory_flags |= REGULATORY_STRICT_REG; ++ wiphy->regulatory_flags &= ~REGULATORY_CUSTOM_REG; ++ wiphy->regulatory_flags &= ~REGULATORY_STRICT_REG; ++ wiphy->regulatory_flags &= ~REGULATORY_DISABLE_BEACON_HINTS; + + rtw_regd_apply_hw_cap_flags(wiphy); + +@@ -434,8 +377,7 @@ int rtw_regd_init(struct rtw_dev *rtwdev, + return -EINVAL; + + rtwdev->regd = rtw_regd_find_reg_by_name(rtwdev->efuse.country_code); +- rtw_regd_init_wiphy(rtwdev, wiphy, reg_notifier); +- rtwdev->regd.region = RTW_REGION_INVALID; ++ rtw_regd_init_wiphy(&rtwdev->regd, wiphy, reg_notifier); + + return 0; + } +@@ -445,21 +387,12 @@ void rtw_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request) + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); + struct rtw_dev *rtwdev = hw->priv; + struct rtw_hal *hal = &rtwdev->hal; +- int ret; + +- ret = rtw_regd_notifier_apply(rtwdev, wiphy, request); +- if (ret) { +- rtw_warn(rtwdev, "failed to apply regulatory from initiator %d: %d\n", +- request->initiator, ret); +- return; +- } ++ rtw_regd_notifier_apply(rtwdev, wiphy, request); + rtw_dbg(rtwdev, RTW_DBG_REGD, + "get alpha2 %c%c from initiator %d, mapping to chplan 0x%x, txregd %d\n", +- request->alpha2[0], request->alpha2[1], +- request->initiator, rtwdev->regd.chplan, +- rtwdev->regd.txpwr_regd); +- +- rtw_phy_adaptivity_set_mode(rtwdev); ++ request->alpha2[0], request->alpha2[1], request->initiator, ++ rtwdev->regd.chplan, rtwdev->regd.txpwr_regd); + + rtw_phy_set_tx_power_level(rtwdev, hal->current_channel); + } +--- a/regd.h ++++ b/regd.h +@@ -68,6 +68,4 @@ int rtw_regd_init(struct rtw_dev *rtwdev, + void (*reg_notifier)(struct wiphy *wiphy, + struct regulatory_request *request)); + void rtw_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request); +-void rtw_regd_init_dfs_region(struct rtw_dev *rtwdev, +- enum nl80211_dfs_regions curr_region); + #endif +--- a/rtw8822b.c ++++ b/rtw8822b.c +@@ -1561,37 +1561,6 @@ static void rtw8822b_bf_config_bfee(struct rtw_dev *rtwdev, struct rtw_vif *vif, + rtw_warn(rtwdev, "wrong bfee role\n"); + } + +-static void rtw8822b_adaptivity_init(struct rtw_dev *rtwdev) +-{ +- rtw_phy_set_edcca_th(rtwdev, 0x7f, 0x7f); +- /* mac edcca state setting */ +- rtw_write32_mask(rtwdev, REG_TX_PTCL_CTRL, BIT_DIS_EDCCA, 0); +- rtw_write32_mask(rtwdev, REG_RD_CTRL, BIT_EDCCA_MSK_CNTDOWN_EN, 1); +- +- rtw_write32_mask(rtwdev, REG_EDCCA_SOURCE, BIT_SOURCE_OPTION, 1); +- rtw_write32_mask(rtwdev, REG_EDCCA_POW_MA, BIT_MA_LEVEL, 0); +- /* edcca decistion opt */ +- rtw_write32_mask(rtwdev, REG_EDCCA_DECISION, BIT_EDCCA_OPTION, 1); +-} +- +-static void rtw8822b_adaptivity(struct rtw_dev *rtwdev) +-{ +- struct rtw_dm_info *dm_info = &rtwdev->dm_info; +- s8 l2h, h2l; +- u8 igi; +- +- igi = dm_info->igi_history[0]; +- if (dm_info->edcca_mode == RTW_EDCCA_NORMAL) { +- l2h = max_t(s8, igi + EDCCA_IGI_L2H_DIFF, EDCCA_TH_L2H_LB); +- h2l = l2h - EDCCA_L2H_H2L_DIFF_NORMAL; +- } else { +- l2h = min_t(s8, igi, dm_info->l2h_th_ini); +- h2l = l2h - EDCCA_L2H_H2L_DIFF; +- } +- +- 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) +@@ -2174,8 +2143,6 @@ static struct rtw_chip_ops rtw8822b_ops = { + .config_bfee = rtw8822b_bf_config_bfee, + .set_gid_table = rtw_bf_set_gid_table, + .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, +--- a/rtw8822c.c ++++ b/rtw8822c.c +@@ -4442,37 +4442,6 @@ static void rtw8822c_pwr_track(struct rtw_dev *rtwdev) + dm_info->pwr_trk_triggered = false; + } + +-static void rtw8822c_adaptivity_init(struct rtw_dev *rtwdev) +-{ +- rtw_phy_set_edcca_th(rtwdev, 0x7f, 0x7f); +- /* mac edcca state setting */ +- rtw_write32_mask(rtwdev, REG_TX_PTCL_CTRL, BIT_DIS_EDCCA, 0); +- rtw_write32_mask(rtwdev, REG_RD_CTRL, BIT_EDCCA_MSK_CNTDOWN_EN, 1); +- /* edcca decistion opt */ +- rtw_write32_mask(rtwdev, REG_EDCCA_DECISION, BIT_EDCCA_OPTION, 0); +-} +- +-static void rtw8822c_adaptivity(struct rtw_dev *rtwdev) +-{ +- struct rtw_dm_info *dm_info = &rtwdev->dm_info; +- s8 l2h, h2l; +- u8 igi; +- +- igi = dm_info->igi_history[0]; +- if (dm_info->edcca_mode == RTW_EDCCA_NORMAL) { +- l2h = max_t(s8, igi + EDCCA_IGI_L2H_DIFF, EDCCA_TH_L2H_LB); +- h2l = l2h - EDCCA_L2H_H2L_DIFF_NORMAL; +- } else { +- if (igi < dm_info->l2h_th_ini - EDCCA_ADC_BACKOFF) +- l2h = igi + EDCCA_ADC_BACKOFF; +- else +- l2h = dm_info->l2h_th_ini; +- h2l = l2h - EDCCA_L2H_H2L_DIFF; +- } +- +- 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) +@@ -4903,8 +4872,6 @@ static struct rtw_chip_ops rtw8822c_ops = { + .cfg_csi_rate = rtw_bf_cfg_csi_rate, + .cfo_init = rtw8822c_cfo_init, + .cfo_track = rtw8822c_cfo_track, +- .adaptivity_init = rtw8822c_adaptivity_init, +- .adaptivity = rtw8822c_adaptivity, + .fill_txdesc_checksum = rtw8822c_fill_txdesc_checksum, + + .coex_set_init = rtw8822c_coex_cfg_init, diff --git a/package/kernel/mac80211/patches/rtl/002-rtw88-Drop-rf_lock.patch b/package/kernel/rtw88-usb/patches/002-drop-rf_lock.patch similarity index 65% rename from package/kernel/mac80211/patches/rtl/002-rtw88-Drop-rf_lock.patch rename to package/kernel/rtw88-usb/patches/002-drop-rf_lock.patch index 4cc979c87..5255721af 100644 --- a/package/kernel/mac80211/patches/rtl/002-rtw88-Drop-rf_lock.patch +++ b/package/kernel/rtw88-usb/patches/002-drop-rf_lock.patch @@ -1,6 +1,21 @@ ---- a/drivers/net/wireless/realtek/rtw88/debug.c -+++ b/drivers/net/wireless/realtek/rtw88/debug.c -@@ -143,7 +143,9 @@ static int rtw_debugfs_get_rf_read(struc +From d57ca103e54e2b3eea7e2603548c58bcc4155541 Mon Sep 17 00:00:00 2001 +From: Sascha Hauer +Date: Fri, 2 Dec 2022 09:12:16 +0100 +Subject: [PATCH] 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 +--- + +--- a/debug.c ++++ b/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; @@ -10,7 +25,7 @@ seq_printf(m, "rf_read path:%d addr:0x%08x mask:0x%08x val=0x%08x\n", path, addr, mask, val); -@@ -401,7 +403,9 @@ static ssize_t rtw_debugfs_set_rf_write( +@@ -418,7 +420,9 @@ static ssize_t rtw_debugfs_set_rf_write(struct file *filp, return count; } @@ -20,7 +35,7 @@ rtw_dbg(rtwdev, RTW_DBG_DEBUGFS, "write_rf path:%d addr:0x%08x mask:0x%08x, val:0x%08x\n", path, addr, mask, val); -@@ -481,6 +485,8 @@ static int rtw_debug_get_rf_dump(struct +@@ -523,6 +527,8 @@ static int rtw_debug_get_rf_dump(struct seq_file *m, void *v) u32 addr, offset, data; u8 path; @@ -29,7 +44,7 @@ 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) { -@@ -495,6 +501,8 @@ static int rtw_debug_get_rf_dump(struct +@@ -537,6 +543,8 @@ static int rtw_debug_get_rf_dump(struct seq_file *m, void *v) seq_puts(m, "\n"); } @@ -38,7 +53,7 @@ return 0; } -@@ -911,6 +919,8 @@ static void dump_gapk_status(struct rtw_ +@@ -1027,6 +1035,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]); @@ -47,7 +62,7 @@ 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); -@@ -920,6 +930,7 @@ static void dump_gapk_status(struct rtw_ +@@ -1036,6 +1046,7 @@ static void dump_gapk_status(struct rtw_dev *rtwdev, struct seq_file *m) txgapk->rf3f_fs[path][i], i); seq_puts(m, "\n"); } @@ -55,8 +70,8 @@ } static int rtw_debugfs_get_dm_cap(struct seq_file *m, void *v) ---- a/drivers/net/wireless/realtek/rtw88/hci.h -+++ b/drivers/net/wireless/realtek/rtw88/hci.h +--- a/hci.h ++++ b/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) @@ -85,9 +100,9 @@ } static inline u32 ---- a/drivers/net/wireless/realtek/rtw88/main.c -+++ b/drivers/net/wireless/realtek/rtw88/main.c -@@ -1839,7 +1839,6 @@ int rtw_core_init(struct rtw_dev *rtwdev +--- a/main.c ++++ b/main.c +@@ -1994,7 +1994,6 @@ int rtw_core_init(struct rtw_dev *rtwdev) skb_queue_head_init(&rtwdev->coex.queue); skb_queue_head_init(&rtwdev->tx_report.queue); @@ -95,9 +110,9 @@ spin_lock_init(&rtwdev->h2c.lock); spin_lock_init(&rtwdev->txq_lock); spin_lock_init(&rtwdev->tx_report.q_lock); ---- a/drivers/net/wireless/realtek/rtw88/main.h -+++ b/drivers/net/wireless/realtek/rtw88/main.h -@@ -1842,9 +1842,6 @@ struct rtw_dev { +--- a/main.h ++++ b/main.h +@@ -1994,9 +1994,6 @@ struct rtw_dev { /* ensures exclusive access from mac80211 callbacks */ struct mutex mutex; diff --git a/package/kernel/mac80211/patches/rtl/003-rtw88-Drop-h2c.lock.patch b/package/kernel/rtw88-usb/patches/003-drop-h2c-lock.patch similarity index 54% rename from package/kernel/mac80211/patches/rtl/003-rtw88-Drop-h2c.lock.patch rename to package/kernel/rtw88-usb/patches/003-drop-h2c-lock.patch index 90f9f4a65..d28cbfd8f 100644 --- a/package/kernel/mac80211/patches/rtl/003-rtw88-Drop-h2c.lock.patch +++ b/package/kernel/rtw88-usb/patches/003-drop-h2c-lock.patch @@ -1,6 +1,20 @@ ---- a/drivers/net/wireless/realtek/rtw88/debug.c -+++ b/drivers/net/wireless/realtek/rtw88/debug.c -@@ -379,7 +379,9 @@ static ssize_t rtw_debugfs_set_h2c(struc +From 1e2701f4079a7906ff3fb43a315925d303e289d8 Mon Sep 17 00:00:00 2001 +From: Sascha Hauer +Date: Fri, 2 Dec 2022 09:12:17 +0100 +Subject: [PATCH] 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 +--- + +--- a/debug.c ++++ b/debug.c +@@ -396,7 +396,9 @@ static ssize_t rtw_debugfs_set_h2c(struct file *filp, return -EINVAL; } @@ -10,9 +24,9 @@ return count; } ---- a/drivers/net/wireless/realtek/rtw88/fw.c -+++ b/drivers/net/wireless/realtek/rtw88/fw.c -@@ -285,7 +285,7 @@ static void rtw_fw_send_h2c_command(stru +--- a/fw.c ++++ b/fw.c +@@ -320,7 +320,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]); @@ -21,7 +35,7 @@ box = rtwdev->h2c.last_box_num; switch (box) { -@@ -307,7 +307,7 @@ static void rtw_fw_send_h2c_command(stru +@@ -342,7 +342,7 @@ static void rtw_fw_send_h2c_command(struct rtw_dev *rtwdev, break; default: WARN(1, "invalid h2c mail box number\n"); @@ -30,7 +44,7 @@ } ret = read_poll_timeout_atomic(rtw_read8, box_state, -@@ -316,7 +316,7 @@ static void rtw_fw_send_h2c_command(stru +@@ -351,7 +351,7 @@ static void rtw_fw_send_h2c_command(struct rtw_dev *rtwdev, if (ret) { rtw_err(rtwdev, "failed to send h2c command\n"); @@ -39,7 +53,7 @@ } for (idx = 0; idx < 4; idx++) -@@ -326,9 +326,6 @@ static void rtw_fw_send_h2c_command(stru +@@ -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; @@ -49,7 +63,7 @@ } void rtw_fw_h2c_cmd_dbg(struct rtw_dev *rtwdev, u8 *h2c) -@@ -340,15 +337,13 @@ static void rtw_fw_send_h2c_packet(struc +@@ -375,15 +372,13 @@ static void rtw_fw_send_h2c_packet(struct rtw_dev *rtwdev, u8 *h2c_pkt) { int ret; @@ -66,9 +80,9 @@ } void ---- a/drivers/net/wireless/realtek/rtw88/main.c -+++ b/drivers/net/wireless/realtek/rtw88/main.c -@@ -1839,7 +1839,6 @@ int rtw_core_init(struct rtw_dev *rtwdev +--- a/main.c ++++ b/main.c +@@ -1994,7 +1994,6 @@ int rtw_core_init(struct rtw_dev *rtwdev) skb_queue_head_init(&rtwdev->coex.queue); skb_queue_head_init(&rtwdev->tx_report.queue); @@ -76,9 +90,9 @@ spin_lock_init(&rtwdev->txq_lock); spin_lock_init(&rtwdev->tx_report.q_lock); ---- a/drivers/net/wireless/realtek/rtw88/main.h -+++ b/drivers/net/wireless/realtek/rtw88/main.h -@@ -1865,8 +1865,6 @@ struct rtw_dev { +--- a/main.h ++++ b/main.h +@@ -2018,8 +2018,6 @@ struct rtw_dev { struct { /* incicate the mail box to use with fw */ u8 last_box_num; @@ -86,4 +100,4 @@ - spinlock_t lock; u32 seq; } h2c; - + diff --git a/package/kernel/rtw88-usb/patches/004-drop-coex-mutex.patch b/package/kernel/rtw88-usb/patches/004-drop-coex-mutex.patch new file mode 100644 index 000000000..cd3af524a --- /dev/null +++ b/package/kernel/rtw88-usb/patches/004-drop-coex-mutex.patch @@ -0,0 +1,74 @@ +From 8647f7f0b9080bc2d2f6e02524782f2f02f159bc Mon Sep 17 00:00:00 2001 +From: Sascha Hauer +Date: Fri, 2 Dec 2022 09:12:18 +0100 +Subject: [PATCH] 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 +--- + +--- a/coex.c ++++ b/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; + } + +--- a/debug.c ++++ b/debug.c +@@ -842,7 +842,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; + } +--- a/main.c ++++ b/main.c +@@ -1998,7 +1998,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); +@@ -2066,7 +2065,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); +--- a/main.h ++++ b/main.h +@@ -1507,8 +1507,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; + diff --git a/package/kernel/mac80211/patches/rtl/005-rtw88-iterate-over-vif-sta-list-non-atomically.patch b/package/kernel/rtw88-usb/patches/005-iterate-over-vif-sta-list-non-atomically.patch similarity index 78% rename from package/kernel/mac80211/patches/rtl/005-rtw88-iterate-over-vif-sta-list-non-atomically.patch rename to package/kernel/rtw88-usb/patches/005-iterate-over-vif-sta-list-non-atomically.patch index e5506a468..87369f827 100644 --- a/package/kernel/mac80211/patches/rtl/005-rtw88-iterate-over-vif-sta-list-non-atomically.patch +++ b/package/kernel/rtw88-usb/patches/005-iterate-over-vif-sta-list-non-atomically.patch @@ -1,6 +1,25 @@ ---- a/drivers/net/wireless/realtek/rtw88/phy.c -+++ b/drivers/net/wireless/realtek/rtw88/phy.c -@@ -240,7 +240,7 @@ static void rtw_phy_stat_rssi(struct rtw +From 78d5bf925f30bf9f79a69ce77386902672defe68 Mon Sep 17 00:00:00 2001 +From: Sascha Hauer +Date: Fri, 2 Dec 2022 09:12:19 +0100 +Subject: [PATCH] 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 +--- + +--- a/phy.c ++++ b/phy.c +@@ -300,7 +300,7 @@ static void rtw_phy_stat_rssi(struct rtw_dev *rtwdev) data.rtwdev = rtwdev; data.min_rssi = U8_MAX; @@ -9,7 +28,7 @@ dm_info->pre_min_rssi = dm_info->min_rssi; dm_info->min_rssi = data.min_rssi; -@@ -484,7 +484,7 @@ static void rtw_phy_ra_info_update(struc +@@ -544,7 +544,7 @@ static void rtw_phy_ra_info_update(struct rtw_dev *rtwdev) if (rtwdev->watch_dog_cnt & 0x3) return; @@ -18,7 +37,7 @@ } static u32 rtw_phy_get_rrsr_mask(struct rtw_dev *rtwdev, u8 rate_idx) -@@ -537,7 +537,7 @@ static void rtw_phy_rrsr_update(struct r +@@ -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; @@ -27,9 +46,9 @@ rtw_write32(rtwdev, REG_RRSR, dm_info->rrsr_val_init & dm_info->rrsr_mask_min); } ---- a/drivers/net/wireless/realtek/rtw88/ps.c -+++ b/drivers/net/wireless/realtek/rtw88/ps.c -@@ -58,7 +58,7 @@ int rtw_leave_ips(struct rtw_dev *rtwdev +--- a/ps.c ++++ b/ps.c +@@ -58,7 +58,7 @@ int rtw_leave_ips(struct rtw_dev *rtwdev) return ret; } @@ -38,9 +57,9 @@ rtw_coex_ips_notify(rtwdev, COEX_IPS_LEAVE); ---- 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 *m +--- a/util.c ++++ b/util.c +@@ -105,3 +105,106 @@ void rtw_desc_to_mcsrate(u16 rate, u8 *mcs, u8 *nss) *mcs = rate - DESC_RATEMCS0; } } @@ -147,8 +166,8 @@ + kfree(vif_entry); + } +} ---- a/drivers/net/wireless/realtek/rtw88/util.h -+++ b/drivers/net/wireless/realtek/rtw88/util.h +--- a/util.h ++++ b/util.h @@ -7,9 +7,6 @@ struct rtw_dev; diff --git a/package/kernel/rtw88-usb/patches/100-update-makefile.patch b/package/kernel/rtw88-usb/patches/100-update-makefile.patch new file mode 100644 index 000000000..170a6bc11 --- /dev/null +++ b/package/kernel/rtw88-usb/patches/100-update-makefile.patch @@ -0,0 +1,25 @@ +--- a/Makefile ++++ b/Makefile +@@ -2,22 +2,6 @@ + KERNELDIR ?= /lib/modules/$(shell uname -r)/build + PWD := $(shell pwd) + +-CONFIG_RTW88_CORE=m +-CONFIG_RTW88_PCI=m +-CONFIG_RTW88_USB=m +-CONFIG_RTW88_8822BE=m +-CONFIG_RTW88_8822BU=m +-CONFIG_RTW88_8822B=m +-CONFIG_RTW88_8821CE=m +-CONFIG_RTW88_8821CU=m +-CONFIG_RTW88_8821C=m +-CONFIG_RTW88_8822CE=m +-CONFIG_RTW88_8822CU=m +-CONFIG_RTW88_8822C=m +-CONFIG_RTW88_8723DE=m +-CONFIG_RTW88_8723DU=m +-CONFIG_RTW88_8723D=m +- + ifneq ($(CONFIG_RTW88_8822BE),m) + ccflags-y += -DCONFIG_RTW88_8822BE=y + endif diff --git a/package/kernel/rtw88-usb/patches/101-wireless-5.14.patch b/package/kernel/rtw88-usb/patches/101-wireless-5.14.patch new file mode 100644 index 000000000..ba8ebfcda --- /dev/null +++ b/package/kernel/rtw88-usb/patches/101-wireless-5.14.patch @@ -0,0 +1,14 @@ +--- a/mac80211.c ++++ b/mac80211.c +@@ -614,7 +614,11 @@ static void rtw_ops_sw_scan_complete(struct ieee80211_hw *hw, + + static void rtw_ops_mgd_prepare_tx(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 14, 0)) ++ struct ieee80211_prep_tx_info *info) ++#else + u16 duration) ++#endif + { + struct rtw_dev *rtwdev = hw->priv; +