]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: rtw88: usb: Further limit the TX aggregation
authorBitterblue Smith <rtl8821cerfe2@gmail.com>
Sun, 16 Jun 2024 19:27:34 +0000 (22:27 +0300)
committerPing-Ke Shih <pkshih@realtek.com>
Fri, 21 Jun 2024 12:41:10 +0000 (20:41 +0800)
Currently the number of frames sent to the chip in a single USB Request
Block is limited only by the size of the TX buffer, which is 20 KiB.
Testing reveals that as many as 13 frames get aggregated. This is more
than what any of the chips would like to receive. RTL8822CU, RTL8822BU,
and RTL8821CU want at most 3 frames, and RTL8723DU wants only 1 frame
per URB.

RTL8723DU in particular reliably malfunctions during a speed test if it
receives more than 1 frame per URB. All traffic seems to stop. Pinging
the AP no longer works.

Fix this problem by limiting the number of frames sent to the chip in a
single URB according to what each chip likes.

Also configure RTL8822CU, RTL8822BU, and RTL8821CU to expect 3 frames
per URB.

RTL8703B may or may not be found in USB devices. Declare that it wants
only 1 frame per URB, just in case.

Tested with RTL8723DU and RTL8811CU.

Cc: stable@vger.kernel.org
Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
Acked-by: Ping-Ke Shih <pkshih@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/cb46ea35-7e59-4742-9c1f-01ceeaad36fb@gmail.com
drivers/net/wireless/realtek/rtw88/mac.c
drivers/net/wireless/realtek/rtw88/main.h
drivers/net/wireless/realtek/rtw88/reg.h
drivers/net/wireless/realtek/rtw88/rtw8703b.c
drivers/net/wireless/realtek/rtw88/rtw8723d.c
drivers/net/wireless/realtek/rtw88/rtw8821c.c
drivers/net/wireless/realtek/rtw88/rtw8822b.c
drivers/net/wireless/realtek/rtw88/rtw8822c.c
drivers/net/wireless/realtek/rtw88/usb.c

index 0dba8aae771603c0e4bd75e32485a168c1dc7e23..564f5988ee82a7a336ee16666a9048430ab8f2b1 100644 (file)
@@ -1201,6 +1201,15 @@ static int __priority_queue_cfg(struct rtw_dev *rtwdev,
        rtw_write16(rtwdev, REG_FIFOPAGE_CTRL_2 + 2, fifo->rsvd_boundary);
        rtw_write16(rtwdev, REG_BCNQ1_BDNY_V1, fifo->rsvd_boundary);
        rtw_write32(rtwdev, REG_RXFF_BNDY, chip->rxff_size - C2H_PKT_BUF - 1);
+
+       if (rtwdev->hci.type == RTW_HCI_TYPE_USB) {
+               rtw_write8_mask(rtwdev, REG_AUTO_LLT_V1, BIT_MASK_BLK_DESC_NUM,
+                               chip->usb_tx_agg_desc_num);
+
+               rtw_write8(rtwdev, REG_AUTO_LLT_V1 + 3, chip->usb_tx_agg_desc_num);
+               rtw_write8_set(rtwdev, REG_TXDMA_OFFSET_CHK + 1, BIT(1));
+       }
+
        rtw_write8_set(rtwdev, REG_AUTO_LLT_V1, BIT_AUTO_INIT_LLT_V1);
 
        if (!check_hw_ready(rtwdev, REG_AUTO_LLT_V1, BIT_AUTO_INIT_LLT_V1, 0))
index 49894331f7b49517e6c49dae002441921ae69ecd..49a3fd4fb7dcdce4e3c1cc00f9c385b1d364ca3f 100644 (file)
@@ -1197,6 +1197,8 @@ struct rtw_chip_info {
        u16 fw_fifo_addr[RTW_FW_FIFO_MAX];
        const struct rtw_fwcd_segs *fwcd_segs;
 
+       u8 usb_tx_agg_desc_num;
+
        u8 default_1ss_tx_path;
 
        bool path_div_supported;
index b122f226924be5d973bdc74fa5b3312df933c2c6..02ef9a77316b481dd702743586571df3588b3ff3 100644 (file)
 #define BIT_MASK_BCN_HEAD_1_V1 0xfff
 #define REG_AUTO_LLT_V1                0x0208
 #define BIT_AUTO_INIT_LLT_V1   BIT(0)
+#define BIT_MASK_BLK_DESC_NUM  GENMASK(7, 4)
 #define REG_DWBCN0_CTRL                0x0208
 #define BIT_BCN_VALID          BIT(16)
 #define REG_TXDMA_OFFSET_CHK   0x020C
index 8919f9e11f0378316181dde526edbc27563da055..222608de33cdec664242d9d6ee5c37df78fdc496 100644 (file)
@@ -2013,6 +2013,7 @@ const struct rtw_chip_info rtw8703b_hw_spec = {
        .tx_stbc = false,
        .max_power_index = 0x3f,
        .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
+       .usb_tx_agg_desc_num = 1, /* Not sure if this chip has USB interface */
 
        .path_div_supported = false,
        .ht_supported = true,
index f8df4c84d39f73224bbb3f2899e7d0d951e1a39a..3fba4054d45f498aefac1c3091ab030c99fb5856 100644 (file)
@@ -2171,6 +2171,7 @@ const struct rtw_chip_info rtw8723d_hw_spec = {
        .band = RTW_BAND_2G,
        .page_size = TX_PAGE_SIZE,
        .dig_min = 0x20,
+       .usb_tx_agg_desc_num = 1,
        .ht_supported = true,
        .vht_supported = false,
        .lps_deep_mode_supported = 0,
index fe5d8e1883509375fca475f0b6e42dc7448d4c1c..526e8de77b3e828d6b50a70faef657558fb33d16 100644 (file)
@@ -2008,6 +2008,7 @@ const struct rtw_chip_info rtw8821c_hw_spec = {
        .band = RTW_BAND_2G | RTW_BAND_5G,
        .page_size = TX_PAGE_SIZE,
        .dig_min = 0x1c,
+       .usb_tx_agg_desc_num = 3,
        .ht_supported = true,
        .vht_supported = true,
        .lps_deep_mode_supported = BIT(LPS_DEEP_MODE_LCLK),
index 3017a9760da8dca8f982679336daafb081e0ef09..2456ff24281801719ce5fafdb80e90a41d674417 100644 (file)
@@ -2548,6 +2548,7 @@ const struct rtw_chip_info rtw8822b_hw_spec = {
        .band = RTW_BAND_2G | RTW_BAND_5G,
        .page_size = TX_PAGE_SIZE,
        .dig_min = 0x1c,
+       .usb_tx_agg_desc_num = 3,
        .ht_supported = true,
        .vht_supported = true,
        .lps_deep_mode_supported = BIT(LPS_DEEP_MODE_LCLK),
index cd965edc29cea3e994f630c1681b7ea4c573df6f..62376d1cca22fc464dae50a630ce3d50e198a398 100644 (file)
@@ -5366,6 +5366,7 @@ const struct rtw_chip_info rtw8822c_hw_spec = {
        .band = RTW_BAND_2G | RTW_BAND_5G,
        .page_size = TX_PAGE_SIZE,
        .dig_min = 0x20,
+       .usb_tx_agg_desc_num = 3,
        .default_1ss_tx_path = BB_PATH_A,
        .path_div_supported = true,
        .ht_supported = true,
index d204d138afe298a1e993a376018efa4977a06f57..057c0ffbe944722f5820a42d3e6c46f2106f2f90 100644 (file)
@@ -379,7 +379,9 @@ static bool rtw_usb_tx_agg_skb(struct rtw_usb *rtwusb, struct sk_buff_head *list
 
                skb_iter = skb_peek(list);
 
-               if (skb_iter && skb_iter->len + skb_head->len <= RTW_USB_MAX_XMITBUF_SZ)
+               if (skb_iter &&
+                   skb_iter->len + skb_head->len <= RTW_USB_MAX_XMITBUF_SZ &&
+                   agg_num < rtwdev->chip->usb_tx_agg_desc_num)
                        __skb_unlink(skb_iter, list);
                else
                        skb_iter = NULL;