1 From 80fe0bc1659c0ccc79d082e426fa376be5df9c04 Mon Sep 17 00:00:00 2001
2 From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
3 Date: Sat, 10 May 2025 15:22:24 +0300
4 Subject: [PATCH] wifi: rtw88: usb: Upload the firmware in bigger chunks
6 RTL8811AU stops responding during the firmware download on some systems:
8 [ 809.256440] rtw_8821au 5-2.1:1.0: Firmware version 42.4.0, H2C version 0
9 [ 812.759142] rtw_8821au 5-2.1:1.0 wlp48s0f4u2u1: renamed from wlan0
10 [ 837.315388] rtw_8821au 1-4:1.0: write register 0x1ef4 failed with -110
11 [ 867.524259] rtw_8821au 1-4:1.0: write register 0x1ef8 failed with -110
12 [ 868.930976] rtw_8821au 5-2.1:1.0 wlp48s0f4u2u1: entered promiscuous mode
13 [ 897.730952] rtw_8821au 1-4:1.0: write register 0x1efc failed with -110
15 Maybe it takes too long when writing the firmware 4 bytes at a time.
17 Write 196 bytes at a time for RTL8821AU, RTL8811AU, and RTL8812AU,
18 and 254 bytes at a time for RTL8723DU. These are the sizes used in
19 their official drivers. Tested with all these chips.
21 Cc: stable@vger.kernel.org
22 Link: https://github.com/lwfinger/rtw88/issues/344
23 Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
24 Acked-by: Ping-Ke Shih <pkshih@realtek.com>
25 Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
26 Link: https://patch.msgid.link/43f1daad-3ec0-4a3b-a50c-9cd9eb2c2f52@gmail.com
28 drivers/net/wireless/realtek/rtw88/hci.h | 8 ++++
29 drivers/net/wireless/realtek/rtw88/mac.c | 11 +++--
30 drivers/net/wireless/realtek/rtw88/mac.h | 2 +
31 drivers/net/wireless/realtek/rtw88/pci.c | 2 +
32 drivers/net/wireless/realtek/rtw88/sdio.c | 2 +
33 drivers/net/wireless/realtek/rtw88/usb.c | 55 +++++++++++++++++++++++
34 6 files changed, 76 insertions(+), 4 deletions(-)
36 --- a/drivers/net/wireless/realtek/rtw88/hci.h
37 +++ b/drivers/net/wireless/realtek/rtw88/hci.h
38 @@ -19,6 +19,8 @@ struct rtw_hci_ops {
39 void (*link_ps)(struct rtw_dev *rtwdev, bool enter);
40 void (*interface_cfg)(struct rtw_dev *rtwdev);
41 void (*dynamic_rx_agg)(struct rtw_dev *rtwdev, bool enable);
42 + void (*write_firmware_page)(struct rtw_dev *rtwdev, u32 page,
43 + const u8 *data, u32 size);
45 int (*write_data_rsvd_page)(struct rtw_dev *rtwdev, u8 *buf, u32 size);
46 int (*write_data_h2c)(struct rtw_dev *rtwdev, u8 *buf, u32 size);
47 @@ -79,6 +81,12 @@ static inline void rtw_hci_dynamic_rx_ag
48 rtwdev->hci.ops->dynamic_rx_agg(rtwdev, enable);
51 +static inline void rtw_hci_write_firmware_page(struct rtw_dev *rtwdev, u32 page,
52 + const u8 *data, u32 size)
54 + rtwdev->hci.ops->write_firmware_page(rtwdev, page, data, size);
58 rtw_hci_write_data_rsvd_page(struct rtw_dev *rtwdev, u8 *buf, u32 size)
60 --- a/drivers/net/wireless/realtek/rtw88/mac.c
61 +++ b/drivers/net/wireless/realtek/rtw88/mac.c
62 @@ -856,8 +856,8 @@ fwdl_ready:
67 -write_firmware_page(struct rtw_dev *rtwdev, u32 page, const u8 *data, u32 size)
68 +void rtw_write_firmware_page(struct rtw_dev *rtwdev, u32 page,
69 + const u8 *data, u32 size)
73 @@ -887,6 +887,7 @@ write_firmware_page(struct rtw_dev *rtwd
74 rtw_write32(rtwdev, write_addr, le32_to_cpu(remain_data));
77 +EXPORT_SYMBOL(rtw_write_firmware_page);
80 download_firmware_legacy(struct rtw_dev *rtwdev, const u8 *data, u32 size)
81 @@ -904,11 +905,13 @@ download_firmware_legacy(struct rtw_dev
82 rtw_write8_set(rtwdev, REG_MCUFW_CTRL, BIT_FWDL_CHK_RPT);
84 for (page = 0; page < total_page; page++) {
85 - write_firmware_page(rtwdev, page, data, DLFW_PAGE_SIZE_LEGACY);
86 + rtw_hci_write_firmware_page(rtwdev, page, data,
87 + DLFW_PAGE_SIZE_LEGACY);
88 data += DLFW_PAGE_SIZE_LEGACY;
91 - write_firmware_page(rtwdev, page, data, last_page_size);
92 + rtw_hci_write_firmware_page(rtwdev, page, data,
95 if (!check_hw_ready(rtwdev, REG_MCUFW_CTRL, BIT_FWDL_CHK_RPT, 1)) {
96 rtw_err(rtwdev, "failed to check download firmware report\n");
97 --- a/drivers/net/wireless/realtek/rtw88/mac.h
98 +++ b/drivers/net/wireless/realtek/rtw88/mac.h
99 @@ -34,6 +34,8 @@ int rtw_pwr_seq_parser(struct rtw_dev *r
100 const struct rtw_pwr_seq_cmd * const *cmd_seq);
101 int rtw_mac_power_on(struct rtw_dev *rtwdev);
102 void rtw_mac_power_off(struct rtw_dev *rtwdev);
103 +void rtw_write_firmware_page(struct rtw_dev *rtwdev, u32 page,
104 + const u8 *data, u32 size);
105 int rtw_download_firmware(struct rtw_dev *rtwdev, struct rtw_fw_state *fw);
106 int rtw_mac_init(struct rtw_dev *rtwdev);
107 void rtw_mac_flush_queues(struct rtw_dev *rtwdev, u32 queues, bool drop);
108 --- a/drivers/net/wireless/realtek/rtw88/pci.c
109 +++ b/drivers/net/wireless/realtek/rtw88/pci.c
116 static bool rtw_disable_msi;
117 static bool rtw_pci_disable_aspm;
118 @@ -1602,6 +1603,7 @@ static const struct rtw_hci_ops rtw_pci_
119 .link_ps = rtw_pci_link_ps,
120 .interface_cfg = rtw_pci_interface_cfg,
121 .dynamic_rx_agg = NULL,
122 + .write_firmware_page = rtw_write_firmware_page,
124 .read8 = rtw_pci_read8,
125 .read16 = rtw_pci_read16,
126 --- a/drivers/net/wireless/realtek/rtw88/sdio.c
127 +++ b/drivers/net/wireless/realtek/rtw88/sdio.c
129 #include <linux/mmc/host.h>
130 #include <linux/mmc/sdio_func.h>
136 @@ -1164,6 +1165,7 @@ static const struct rtw_hci_ops rtw_sdio
137 .link_ps = rtw_sdio_link_ps,
138 .interface_cfg = rtw_sdio_interface_cfg,
139 .dynamic_rx_agg = NULL,
140 + .write_firmware_page = rtw_write_firmware_page,
142 .read8 = rtw_sdio_read8,
143 .read16 = rtw_sdio_read16,
144 --- a/drivers/net/wireless/realtek/rtw88/usb.c
145 +++ b/drivers/net/wireless/realtek/rtw88/usb.c
146 @@ -165,6 +165,60 @@ static void rtw_usb_write32(struct rtw_d
147 rtw_usb_write(rtwdev, addr, val, 4);
150 +static void rtw_usb_write_firmware_page(struct rtw_dev *rtwdev, u32 page,
151 + const u8 *data, u32 size)
153 + struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
154 + struct usb_device *udev = rtwusb->udev;
155 + u32 addr = FW_START_ADDR_LEGACY;
156 + u8 *data_dup, *buf;
160 + switch (rtwdev->chip->id) {
161 + case RTW_CHIP_TYPE_8723D:
169 + data_dup = kmemdup(data, size, GFP_KERNEL);
175 + rtw_write32_mask(rtwdev, REG_MCUFW_CTRL, BIT_ROM_PGE, page);
178 + if (size >= block_size)
180 + else if (size >= 8)
185 + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
186 + RTW_USB_CMD_REQ, RTW_USB_CMD_WRITE,
187 + addr, 0, buf, n, 500);
189 + if (ret != -ENODEV)
191 + "write 0x%x len %d failed: %d\n",
204 static int dma_mapping_to_ep(enum rtw_dma_mapping dma_mapping)
206 switch (dma_mapping) {
207 @@ -855,6 +909,7 @@ static const struct rtw_hci_ops rtw_usb_
208 .link_ps = rtw_usb_link_ps,
209 .interface_cfg = rtw_usb_interface_cfg,
210 .dynamic_rx_agg = rtw_usb_dynamic_rx_agg,
211 + .write_firmware_page = rtw_usb_write_firmware_page,
213 .write8 = rtw_usb_write8,
214 .write16 = rtw_usb_write16,