diff options
Diffstat (limited to 'drivers/net/wireless/realtek/rtw88/usb.c')
-rw-r--r-- | drivers/net/wireless/realtek/rtw88/usb.c | 65 |
1 files changed, 60 insertions, 5 deletions
diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c index c4908db4ff0e..3b5126ffc81a 100644 --- a/drivers/net/wireless/realtek/rtw88/usb.c +++ b/drivers/net/wireless/realtek/rtw88/usb.c @@ -139,7 +139,7 @@ static void rtw_usb_write(struct rtw_dev *rtwdev, u32 addr, u32 val, int len) ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), RTW_USB_CMD_REQ, RTW_USB_CMD_WRITE, - addr, 0, data, len, 30000); + addr, 0, data, len, 500); if (ret < 0 && ret != -ENODEV && count++ < 4) rtw_err(rtwdev, "write register 0x%x failed with %d\n", addr, ret); @@ -165,6 +165,60 @@ static void rtw_usb_write32(struct rtw_dev *rtwdev, u32 addr, u32 val) rtw_usb_write(rtwdev, addr, val, 4); } +static void rtw_usb_write_firmware_page(struct rtw_dev *rtwdev, u32 page, + const u8 *data, u32 size) +{ + struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); + struct usb_device *udev = rtwusb->udev; + u32 addr = FW_START_ADDR_LEGACY; + u8 *data_dup, *buf; + u32 n, block_size; + int ret; + + switch (rtwdev->chip->id) { + case RTW_CHIP_TYPE_8723D: + block_size = 254; + break; + default: + block_size = 196; + break; + } + + data_dup = kmemdup(data, size, GFP_KERNEL); + if (!data_dup) + return; + + buf = data_dup; + + rtw_write32_mask(rtwdev, REG_MCUFW_CTRL, BIT_ROM_PGE, page); + + while (size > 0) { + if (size >= block_size) + n = block_size; + else if (size >= 8) + n = 8; + else + n = 1; + + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + RTW_USB_CMD_REQ, RTW_USB_CMD_WRITE, + addr, 0, buf, n, 500); + if (ret != n) { + if (ret != -ENODEV) + rtw_err(rtwdev, + "write 0x%x len %d failed: %d\n", + addr, n, ret); + break; + } + + addr += n; + buf += n; + size -= n; + } + + kfree(data_dup); +} + static int dma_mapping_to_ep(enum rtw_dma_mapping dma_mapping) { switch (dma_mapping) { @@ -866,6 +920,7 @@ static void rtw_usb_dynamic_rx_agg(struct rtw_dev *rtwdev, bool enable) case RTW_CHIP_TYPE_8822C: case RTW_CHIP_TYPE_8822B: case RTW_CHIP_TYPE_8821C: + case RTW_CHIP_TYPE_8814A: rtw_usb_dynamic_rx_agg_v1(rtwdev, enable); break; case RTW_CHIP_TYPE_8821A: @@ -881,7 +936,7 @@ static void rtw_usb_dynamic_rx_agg(struct rtw_dev *rtwdev, bool enable) } } -static struct rtw_hci_ops rtw_usb_ops = { +static const 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, @@ -891,6 +946,7 @@ static struct rtw_hci_ops rtw_usb_ops = { .link_ps = rtw_usb_link_ps, .interface_cfg = rtw_usb_interface_cfg, .dynamic_rx_agg = rtw_usb_dynamic_rx_agg, + .write_firmware_page = rtw_usb_write_firmware_page, .write8 = rtw_usb_write8, .write16 = rtw_usb_write16, @@ -948,7 +1004,6 @@ static void rtw_usb_deinit_rx(struct rtw_dev *rtwdev) skb_queue_purge(&rtwusb->rx_queue); - flush_workqueue(rtwusb->rxwq); destroy_workqueue(rtwusb->rxwq); skb_queue_purge(&rtwusb->rx_free_queue); @@ -977,7 +1032,6 @@ static void rtw_usb_deinit_tx(struct rtw_dev *rtwdev) { struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); - flush_workqueue(rtwusb->txwq); destroy_workqueue(rtwusb->txwq); rtw_usb_tx_queue_purge(rtwusb); } @@ -1094,7 +1148,8 @@ static int rtw_usb_switch_mode_new(struct rtw_dev *rtwdev) static bool rtw_usb3_chip_old(u8 chip_id) { - return chip_id == RTW_CHIP_TYPE_8812A; + return chip_id == RTW_CHIP_TYPE_8812A || + chip_id == RTW_CHIP_TYPE_8814A; } static bool rtw_usb3_chip_new(u8 chip_id) |