diff options
Diffstat (limited to 'drivers/net/wireless/realtek/rtw88')
37 files changed, 246 insertions, 100 deletions
diff --git a/drivers/net/wireless/realtek/rtw88/coex.c b/drivers/net/wireless/realtek/rtw88/coex.c index c929db1e53ca..64904278ddad 100644 --- a/drivers/net/wireless/realtek/rtw88/coex.c +++ b/drivers/net/wireless/realtek/rtw88/coex.c @@ -309,7 +309,7 @@ static void rtw_coex_tdma_timer_base(struct rtw_dev *rtwdev, u8 type) { struct rtw_coex *coex = &rtwdev->coex; struct rtw_coex_stat *coex_stat = &coex->stat; - u8 para[2] = {0}; + u8 para[6] = {}; u8 times; u16 tbtt_interval = coex_stat->wl_beacon_interval; diff --git a/drivers/net/wireless/realtek/rtw88/fw.c b/drivers/net/wireless/realtek/rtw88/fw.c index 6b563ac489a7..4fc78b882080 100644 --- a/drivers/net/wireless/realtek/rtw88/fw.c +++ b/drivers/net/wireless/realtek/rtw88/fw.c @@ -1466,7 +1466,7 @@ void rtw_add_rsvd_page_sta(struct rtw_dev *rtwdev, int rtw_fw_write_data_rsvd_page(struct rtw_dev *rtwdev, u16 pg_addr, u8 *buf, u32 size) { - u8 bckp[2]; + u8 bckp[3]; u8 val; u16 rsvd_pg_head; u32 bcn_valid_addr; @@ -1478,6 +1478,8 @@ int rtw_fw_write_data_rsvd_page(struct rtw_dev *rtwdev, u16 pg_addr, if (!size) return -EINVAL; + bckp[2] = rtw_read8(rtwdev, REG_BCN_CTRL); + if (rtw_chip_wcpu_11n(rtwdev)) { rtw_write32_set(rtwdev, REG_DWBCN0_CTRL, BIT_BCN_VALID); } else { @@ -1491,6 +1493,9 @@ int rtw_fw_write_data_rsvd_page(struct rtw_dev *rtwdev, u16 pg_addr, val |= BIT_ENSWBCN >> 8; rtw_write8(rtwdev, REG_CR + 1, val); + rtw_write8(rtwdev, REG_BCN_CTRL, + (bckp[2] & ~BIT_EN_BCN_FUNCTION) | BIT_DIS_TSF_UDT); + if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_PCIE) { val = rtw_read8(rtwdev, REG_FWHW_TXQ_CTRL + 2); bckp[1] = val; @@ -1521,6 +1526,7 @@ restore: rsvd_pg_head = rtwdev->fifo.rsvd_boundary; rtw_write16(rtwdev, REG_FIFOPAGE_CTRL_2, rsvd_pg_head | BIT_BCN_VALID_V1); + rtw_write8(rtwdev, REG_BCN_CTRL, bckp[2]); if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_PCIE) rtw_write8(rtwdev, REG_FWHW_TXQ_CTRL + 2, bckp[1]); rtw_write8(rtwdev, REG_CR + 1, bckp[0]); diff --git a/drivers/net/wireless/realtek/rtw88/hci.h b/drivers/net/wireless/realtek/rtw88/hci.h index 96aeda26014e..d4bee9c3ecfe 100644 --- a/drivers/net/wireless/realtek/rtw88/hci.h +++ b/drivers/net/wireless/realtek/rtw88/hci.h @@ -19,6 +19,8 @@ struct rtw_hci_ops { void (*link_ps)(struct rtw_dev *rtwdev, bool enter); void (*interface_cfg)(struct rtw_dev *rtwdev); void (*dynamic_rx_agg)(struct rtw_dev *rtwdev, bool enable); + void (*write_firmware_page)(struct rtw_dev *rtwdev, u32 page, + const u8 *data, u32 size); int (*write_data_rsvd_page)(struct rtw_dev *rtwdev, u8 *buf, u32 size); int (*write_data_h2c)(struct rtw_dev *rtwdev, u8 *buf, u32 size); @@ -79,6 +81,12 @@ static inline void rtw_hci_dynamic_rx_agg(struct rtw_dev *rtwdev, bool enable) rtwdev->hci.ops->dynamic_rx_agg(rtwdev, enable); } +static inline void rtw_hci_write_firmware_page(struct rtw_dev *rtwdev, u32 page, + const u8 *data, u32 size) +{ + rtwdev->hci.ops->write_firmware_page(rtwdev, page, data, size); +} + static inline int rtw_hci_write_data_rsvd_page(struct rtw_dev *rtwdev, u8 *buf, u32 size) { diff --git a/drivers/net/wireless/realtek/rtw88/mac.c b/drivers/net/wireless/realtek/rtw88/mac.c index 0491f501c138..f66d1b302dc5 100644 --- a/drivers/net/wireless/realtek/rtw88/mac.c +++ b/drivers/net/wireless/realtek/rtw88/mac.c @@ -856,8 +856,8 @@ fwdl_ready: } } -static void -write_firmware_page(struct rtw_dev *rtwdev, u32 page, const u8 *data, u32 size) +void rtw_write_firmware_page(struct rtw_dev *rtwdev, u32 page, + const u8 *data, u32 size) { u32 val32; u32 block_nr; @@ -887,6 +887,7 @@ write_firmware_page(struct rtw_dev *rtwdev, u32 page, const u8 *data, u32 size) rtw_write32(rtwdev, write_addr, le32_to_cpu(remain_data)); } } +EXPORT_SYMBOL(rtw_write_firmware_page); static int download_firmware_legacy(struct rtw_dev *rtwdev, const u8 *data, u32 size) @@ -904,11 +905,13 @@ download_firmware_legacy(struct rtw_dev *rtwdev, const u8 *data, u32 size) rtw_write8_set(rtwdev, REG_MCUFW_CTRL, BIT_FWDL_CHK_RPT); for (page = 0; page < total_page; page++) { - write_firmware_page(rtwdev, page, data, DLFW_PAGE_SIZE_LEGACY); + rtw_hci_write_firmware_page(rtwdev, page, data, + DLFW_PAGE_SIZE_LEGACY); data += DLFW_PAGE_SIZE_LEGACY; } if (last_page_size) - write_firmware_page(rtwdev, page, data, last_page_size); + rtw_hci_write_firmware_page(rtwdev, page, data, + last_page_size); if (!check_hw_ready(rtwdev, REG_MCUFW_CTRL, BIT_FWDL_CHK_RPT, 1)) { rtw_err(rtwdev, "failed to check download firmware report\n"); diff --git a/drivers/net/wireless/realtek/rtw88/mac.h b/drivers/net/wireless/realtek/rtw88/mac.h index 6905e2747372..e92b1483728d 100644 --- a/drivers/net/wireless/realtek/rtw88/mac.h +++ b/drivers/net/wireless/realtek/rtw88/mac.h @@ -34,6 +34,8 @@ int rtw_pwr_seq_parser(struct rtw_dev *rtwdev, const struct rtw_pwr_seq_cmd * const *cmd_seq); int rtw_mac_power_on(struct rtw_dev *rtwdev); void rtw_mac_power_off(struct rtw_dev *rtwdev); +void rtw_write_firmware_page(struct rtw_dev *rtwdev, u32 page, + const u8 *data, u32 size); int rtw_download_firmware(struct rtw_dev *rtwdev, struct rtw_fw_state *fw); int rtw_mac_init(struct rtw_dev *rtwdev); void rtw_mac_flush_queues(struct rtw_dev *rtwdev, u32 queues, bool drop); diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c index 026fbf4ad9cc..77f9fbe1870c 100644 --- a/drivers/net/wireless/realtek/rtw88/mac80211.c +++ b/drivers/net/wireless/realtek/rtw88/mac80211.c @@ -396,6 +396,8 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw, if (rtw_bf_support) rtw_bf_assoc(rtwdev, vif, conf); + rtw_set_ampdu_factor(rtwdev, vif, conf); + rtw_fw_beacon_filter_config(rtwdev, true, vif); } else { rtw_leave_lps(rtwdev); diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c index 959f56a3cc1a..c4de5d114eda 100644 --- a/drivers/net/wireless/realtek/rtw88/main.c +++ b/drivers/net/wireless/realtek/rtw88/main.c @@ -2242,7 +2242,8 @@ int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw) ieee80211_hw_set(hw, SUPPORTS_PS); ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS); ieee80211_hw_set(hw, SUPPORT_FAST_XMIT); - ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU); + if (rtwdev->chip->amsdu_in_ampdu) + ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU); ieee80211_hw_set(hw, HAS_RATE_CONTROL); ieee80211_hw_set(hw, TX_AMSDU); ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS); @@ -2447,6 +2448,38 @@ void rtw_core_enable_beacon(struct rtw_dev *rtwdev, bool enable) } } +void rtw_set_ampdu_factor(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf) +{ + const struct rtw_chip_ops *ops = rtwdev->chip->ops; + struct ieee80211_sta *sta; + u8 factor = 0xff; + + if (!ops->set_ampdu_factor) + return; + + rcu_read_lock(); + + sta = ieee80211_find_sta(vif, bss_conf->bssid); + if (!sta) { + rcu_read_unlock(); + rtw_warn(rtwdev, "%s: failed to find station %pM\n", + __func__, bss_conf->bssid); + return; + } + + if (sta->deflink.vht_cap.vht_supported) + factor = u32_get_bits(sta->deflink.vht_cap.cap, + IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK); + else if (sta->deflink.ht_cap.ht_supported) + factor = sta->deflink.ht_cap.ampdu_factor; + + rcu_read_unlock(); + + if (factor != 0xff) + ops->set_ampdu_factor(rtwdev, factor); +} + MODULE_AUTHOR("Realtek Corporation"); MODULE_DESCRIPTION("Realtek 802.11ac wireless core module"); MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h index 02343e059fd9..b0f1fabe9554 100644 --- a/drivers/net/wireless/realtek/rtw88/main.h +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -878,6 +878,7 @@ struct rtw_chip_ops { u32 antenna_rx); void (*cfg_ldo25)(struct rtw_dev *rtwdev, bool enable); void (*efuse_grant)(struct rtw_dev *rtwdev, bool enable); + void (*set_ampdu_factor)(struct rtw_dev *rtwdev, u8 factor); void (*false_alarm_statistics)(struct rtw_dev *rtwdev); void (*phy_calibration)(struct rtw_dev *rtwdev); void (*dpk_track)(struct rtw_dev *rtwdev); @@ -1229,6 +1230,7 @@ struct rtw_chip_info { u16 fw_fifo_addr[RTW_FW_FIFO_MAX]; const struct rtw_fwcd_segs *fwcd_segs; + bool amsdu_in_ampdu; u8 usb_tx_agg_desc_num; bool hw_feature_report; u8 c2h_ra_report_size; @@ -2272,4 +2274,6 @@ void rtw_update_channel(struct rtw_dev *rtwdev, u8 center_channel, void rtw_core_port_switch(struct rtw_dev *rtwdev, struct ieee80211_vif *vif); bool rtw_core_check_sta_active(struct rtw_dev *rtwdev); void rtw_core_enable_beacon(struct rtw_dev *rtwdev, bool enable); +void rtw_set_ampdu_factor(struct rtw_dev *rtwdev, struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf); #endif diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c index bb4c4ccb31d4..7f2b6dc21f56 100644 --- a/drivers/net/wireless/realtek/rtw88/pci.c +++ b/drivers/net/wireless/realtek/rtw88/pci.c @@ -12,6 +12,7 @@ #include "fw.h" #include "ps.h" #include "debug.h" +#include "mac.h" static bool rtw_disable_msi; static bool rtw_pci_disable_aspm; @@ -1602,6 +1603,7 @@ static const struct rtw_hci_ops rtw_pci_ops = { .link_ps = rtw_pci_link_ps, .interface_cfg = rtw_pci_interface_cfg, .dynamic_rx_agg = NULL, + .write_firmware_page = rtw_write_firmware_page, .read8 = rtw_pci_read8, .read16 = rtw_pci_read16, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8703b.c b/drivers/net/wireless/realtek/rtw88/rtw8703b.c index 1d232adbdd7e..9e6700c43a63 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8703b.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8703b.c @@ -519,15 +519,6 @@ static const struct rtw_rqpn rqpn_table_8703b[] = { RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH}, }; -/* Default power index table for RTL8703B, used if EFUSE does not - * contain valid data. Replaces EFUSE data from offset 0x10 (start of - * txpwr_idx_table). - */ -static const u8 rtw8703b_txpwr_idx_table[] = { - 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, - 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x02 -}; - static void try_mac_from_devicetree(struct rtw_dev *rtwdev) { struct device_node *node = rtwdev->dev->of_node; @@ -544,15 +535,9 @@ static void try_mac_from_devicetree(struct rtw_dev *rtwdev) } } -#define DBG_EFUSE_FIX(rtwdev, name) \ - rtw_dbg(rtwdev, RTW_DBG_EFUSE, "Fixed invalid EFUSE value: " \ - # name "=0x%x\n", rtwdev->efuse.name) - static int rtw8703b_read_efuse(struct rtw_dev *rtwdev, u8 *log_map) { struct rtw_efuse *efuse = &rtwdev->efuse; - u8 *pwr = (u8 *)efuse->txpwr_idx_table; - bool valid = false; int ret; ret = rtw8723x_read_efuse(rtwdev, log_map); @@ -562,51 +547,6 @@ static int rtw8703b_read_efuse(struct rtw_dev *rtwdev, u8 *log_map) if (!is_valid_ether_addr(efuse->addr)) try_mac_from_devicetree(rtwdev); - /* If TX power index table in EFUSE is invalid, fall back to - * built-in table. - */ - for (int i = 0; i < ARRAY_SIZE(rtw8703b_txpwr_idx_table); i++) - if (pwr[i] != 0xff) { - valid = true; - break; - } - if (!valid) { - for (int i = 0; i < ARRAY_SIZE(rtw8703b_txpwr_idx_table); i++) - pwr[i] = rtw8703b_txpwr_idx_table[i]; - rtw_dbg(rtwdev, RTW_DBG_EFUSE, - "Replaced invalid EFUSE TX power index table."); - rtw8723x_debug_txpwr_limit(rtwdev, - efuse->txpwr_idx_table, 2); - } - - /* Override invalid antenna settings. */ - if (efuse->bt_setting == 0xff) { - /* shared antenna */ - efuse->bt_setting |= BIT(0); - /* RF path A */ - efuse->bt_setting &= ~BIT(6); - DBG_EFUSE_FIX(rtwdev, bt_setting); - } - - /* Override invalid board options: The coex code incorrectly - * assumes that if bits 6 & 7 are set the board doesn't - * support coex. Regd is also derived from rf_board_option and - * should be 0 if there's no valid data. - */ - if (efuse->rf_board_option == 0xff) { - efuse->regd = 0; - efuse->rf_board_option &= GENMASK(5, 0); - DBG_EFUSE_FIX(rtwdev, rf_board_option); - } - - /* Override invalid crystal cap setting, default comes from - * vendor driver. Chip specific. - */ - if (efuse->crystal_cap == 0xff) { - efuse->crystal_cap = 0x20; - DBG_EFUSE_FIX(rtwdev, crystal_cap); - } - return 0; } @@ -1904,6 +1844,7 @@ static const struct rtw_chip_ops rtw8703b_ops = { .set_antenna = NULL, .cfg_ldo25 = rtw8723x_cfg_ldo25, .efuse_grant = rtw8723x_efuse_grant, + .set_ampdu_factor = NULL, .false_alarm_statistics = rtw8723x_false_alarm_statistics, .phy_calibration = rtw8703b_phy_calibration, .dpk_track = NULL, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723cs.c b/drivers/net/wireless/realtek/rtw88/rtw8723cs.c index 8d38d36be8c0..1f98d35a8dd1 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8723cs.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8723cs.c @@ -19,7 +19,7 @@ static const struct sdio_device_id rtw_8723cs_id_table[] = { MODULE_DEVICE_TABLE(sdio, rtw_8723cs_id_table); static struct sdio_driver rtw_8723cs_driver = { - .name = "rtw8723cs", + .name = KBUILD_MODNAME, .id_table = rtw_8723cs_id_table, .probe = rtw_sdio_probe, .remove = rtw_sdio_remove, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c index 87715bd54860..31876e708f9e 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c @@ -1404,6 +1404,7 @@ static const struct rtw_chip_ops rtw8723d_ops = { .set_antenna = NULL, .cfg_ldo25 = rtw8723x_cfg_ldo25, .efuse_grant = rtw8723x_efuse_grant, + .set_ampdu_factor = NULL, .false_alarm_statistics = rtw8723x_false_alarm_statistics, .phy_calibration = rtw8723d_phy_calibration, .cck_pd_set = rtw8723d_phy_cck_pd_set, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723de.c b/drivers/net/wireless/realtek/rtw88/rtw8723de.c index abbaafa32851..87c8bc9d18a9 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8723de.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8723de.c @@ -17,7 +17,7 @@ static const struct pci_device_id rtw_8723de_id_table[] = { MODULE_DEVICE_TABLE(pci, rtw_8723de_id_table); static struct pci_driver rtw_8723de_driver = { - .name = "rtw_8723de", + .name = KBUILD_MODNAME, .id_table = rtw_8723de_id_table, .probe = rtw_pci_probe, .remove = rtw_pci_remove, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723ds.c b/drivers/net/wireless/realtek/rtw88/rtw8723ds.c index e5b6960ba0a0..206b77e5b98e 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8723ds.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8723ds.c @@ -25,7 +25,7 @@ static const struct sdio_device_id rtw_8723ds_id_table[] = { MODULE_DEVICE_TABLE(sdio, rtw_8723ds_id_table); static struct sdio_driver rtw_8723ds_driver = { - .name = "rtw_8723ds", + .name = KBUILD_MODNAME, .probe = rtw_sdio_probe, .remove = rtw_sdio_remove, .id_table = rtw_8723ds_id_table, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723du.c b/drivers/net/wireless/realtek/rtw88/rtw8723du.c index 322a805da76b..b661a26e0e22 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8723du.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8723du.c @@ -24,7 +24,7 @@ static int rtw8723du_probe(struct usb_interface *intf, } static struct usb_driver rtw_8723du_driver = { - .name = "rtw_8723du", + .name = KBUILD_MODNAME, .id_table = rtw_8723du_id_table, .probe = rtw8723du_probe, .disconnect = rtw_usb_disconnect, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723x.c b/drivers/net/wireless/realtek/rtw88/rtw8723x.c index 69f73cb5b4cd..4c77963fdd37 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8723x.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8723x.c @@ -69,6 +69,9 @@ static void __rtw8723x_lck(struct rtw_dev *rtwdev) #define DBG_EFUSE_2BYTE(rtwdev, map, name) \ rtw_dbg(rtwdev, RTW_DBG_EFUSE, # name "=0x%02x%02x\n", \ (map)->name[0], (map)->name[1]) +#define DBG_EFUSE_FIX(rtwdev, name) \ + rtw_dbg(rtwdev, RTW_DBG_EFUSE, "Fixed invalid EFUSE value: " \ + # name "=0x%x\n", rtwdev->efuse.name) static void rtw8723xe_efuse_debug(struct rtw_dev *rtwdev, struct rtw8723x_efuse *map) @@ -238,10 +241,21 @@ static void rtw8723xs_efuse_parsing(struct rtw_efuse *efuse, ether_addr_copy(efuse->addr, map->s.mac_addr); } +/* Default power index table for RTL8703B/RTL8723D, used if EFUSE does + * not contain valid data. Replaces EFUSE data from offset 0x10 (start + * of txpwr_idx_table). + */ +static const u8 rtw8723x_txpwr_idx_table[] = { + 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, + 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x02 +}; + static int __rtw8723x_read_efuse(struct rtw_dev *rtwdev, u8 *log_map) { struct rtw_efuse *efuse = &rtwdev->efuse; + u8 *pwr = (u8 *)efuse->txpwr_idx_table; struct rtw8723x_efuse *map; + bool valid = false; int i; map = (struct rtw8723x_efuse *)log_map; @@ -279,6 +293,51 @@ static int __rtw8723x_read_efuse(struct rtw_dev *rtwdev, u8 *log_map) return -EOPNOTSUPP; } + /* If TX power index table in EFUSE is invalid, fall back to + * built-in table. + */ + for (i = 0; i < ARRAY_SIZE(rtw8723x_txpwr_idx_table); i++) + if (pwr[i] != 0xff) { + valid = true; + break; + } + if (!valid) { + for (i = 0; i < ARRAY_SIZE(rtw8723x_txpwr_idx_table); i++) + pwr[i] = rtw8723x_txpwr_idx_table[i]; + rtw_dbg(rtwdev, RTW_DBG_EFUSE, + "Replaced invalid EFUSE TX power index table."); + rtw8723x_debug_txpwr_limit(rtwdev, + efuse->txpwr_idx_table, 2); + } + + /* Override invalid antenna settings. */ + if (efuse->bt_setting == 0xff) { + /* shared antenna */ + efuse->bt_setting |= BIT(0); + /* RF path A */ + efuse->bt_setting &= ~BIT(6); + DBG_EFUSE_FIX(rtwdev, bt_setting); + } + + /* Override invalid board options: The coex code incorrectly + * assumes that if bits 6 & 7 are set the board doesn't + * support coex. Regd is also derived from rf_board_option and + * should be 0 if there's no valid data. + */ + if (efuse->rf_board_option == 0xff) { + efuse->regd = 0; + efuse->rf_board_option &= GENMASK(5, 0); + DBG_EFUSE_FIX(rtwdev, rf_board_option); + } + + /* Override invalid crystal cap setting, default comes from + * vendor driver. Chip specific. + */ + if (efuse->crystal_cap == 0xff) { + efuse->crystal_cap = 0x20; + DBG_EFUSE_FIX(rtwdev, crystal_cap); + } + return 0; } diff --git a/drivers/net/wireless/realtek/rtw88/rtw8812a.c b/drivers/net/wireless/realtek/rtw88/rtw8812a.c index f9ba2aa2928a..c2ef41767ff9 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8812a.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8812a.c @@ -925,6 +925,7 @@ static const struct rtw_chip_ops rtw8812a_ops = { .set_tx_power_index = rtw88xxa_set_tx_power_index, .cfg_ldo25 = rtw8812a_cfg_ldo25, .efuse_grant = rtw88xxa_efuse_grant, + .set_ampdu_factor = NULL, .false_alarm_statistics = rtw88xxa_false_alarm_statistics, .phy_calibration = rtw8812a_phy_calibration, .cck_pd_set = rtw88xxa_phy_cck_pd_set, @@ -1075,6 +1076,7 @@ const struct rtw_chip_info rtw8812a_hw_spec = { .rfe_defs = rtw8812a_rfe_defs, .rfe_defs_size = ARRAY_SIZE(rtw8812a_rfe_defs), .rx_ldpc = false, + .amsdu_in_ampdu = true, .hw_feature_report = false, .c2h_ra_report_size = 4, .old_datarate_fb_limit = true, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8812au.c b/drivers/net/wireless/realtek/rtw88/rtw8812au.c index e18995f4cc78..dfea89670372 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8812au.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8812au.c @@ -82,7 +82,7 @@ static const struct usb_device_id rtw_8812au_id_table[] = { MODULE_DEVICE_TABLE(usb, rtw_8812au_id_table); static struct usb_driver rtw_8812au_driver = { - .name = "rtw_8812au", + .name = KBUILD_MODNAME, .id_table = rtw_8812au_id_table, .probe = rtw_usb_probe, .disconnect = rtw_usb_disconnect, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8814a.c b/drivers/net/wireless/realtek/rtw88/rtw8814a.c index cfd35d40d46e..44dd3090484b 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8814a.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8814a.c @@ -1332,6 +1332,16 @@ static void rtw8814a_cfg_ldo25(struct rtw_dev *rtwdev, bool enable) { } +/* Without this RTL8814A sends too many frames and (some?) 11n AP + * can't handle it, resulting in low TX speed. Other chips seem fine. + */ +static void rtw8814a_set_ampdu_factor(struct rtw_dev *rtwdev, u8 factor) +{ + factor = min_t(u8, factor, IEEE80211_VHT_MAX_AMPDU_256K); + + rtw_write32(rtwdev, REG_AMPDU_MAX_LENGTH, (8192 << factor) - 1); +} + static void rtw8814a_false_alarm_statistics(struct rtw_dev *rtwdev) { struct rtw_dm_info *dm_info = &rtwdev->dm_info; @@ -2051,6 +2061,7 @@ static const struct rtw_chip_ops rtw8814a_ops = { .set_antenna = NULL, .cfg_ldo25 = rtw8814a_cfg_ldo25, .efuse_grant = rtw8814a_efuse_grant, + .set_ampdu_factor = rtw8814a_set_ampdu_factor, .false_alarm_statistics = rtw8814a_false_alarm_statistics, .phy_calibration = rtw8814a_phy_calibration, .cck_pd_set = rtw8814a_phy_cck_pd_set, @@ -2189,6 +2200,7 @@ const struct rtw_chip_info rtw8814a_hw_spec = { .rx_ldpc = true, .max_power_index = 0x3f, .ampdu_density = IEEE80211_HT_MPDU_DENSITY_2, + .amsdu_in_ampdu = false, /* RX speed is better without AMSDU */ .usb_tx_agg_desc_num = 3, .hw_feature_report = false, .c2h_ra_report_size = 6, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8814ae.c b/drivers/net/wireless/realtek/rtw88/rtw8814ae.c index 54d2e20a7764..c7436f1c8d40 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8814ae.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8814ae.c @@ -17,7 +17,7 @@ static const struct pci_device_id rtw_8814ae_id_table[] = { MODULE_DEVICE_TABLE(pci, rtw_8814ae_id_table); static struct pci_driver rtw_8814ae_driver = { - .name = "rtw_8814ae", + .name = KBUILD_MODNAME, .id_table = rtw_8814ae_id_table, .probe = rtw_pci_probe, .remove = rtw_pci_remove, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8814au.c b/drivers/net/wireless/realtek/rtw88/rtw8814au.c index afe045fb84de..1a0886ec17dd 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8814au.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8814au.c @@ -42,7 +42,7 @@ static const struct usb_device_id rtw_8814au_id_table[] = { MODULE_DEVICE_TABLE(usb, rtw_8814au_id_table); static struct usb_driver rtw_8814au_driver = { - .name = "rtw_8814au", + .name = KBUILD_MODNAME, .id_table = rtw_8814au_id_table, .probe = rtw_usb_probe, .disconnect = rtw_usb_disconnect, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821a.c b/drivers/net/wireless/realtek/rtw88/rtw8821a.c index f68239b07319..413aec694c33 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8821a.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8821a.c @@ -871,6 +871,7 @@ static const struct rtw_chip_ops rtw8821a_ops = { .set_tx_power_index = rtw88xxa_set_tx_power_index, .cfg_ldo25 = rtw8821a_cfg_ldo25, .efuse_grant = rtw88xxa_efuse_grant, + .set_ampdu_factor = NULL, .false_alarm_statistics = rtw88xxa_false_alarm_statistics, .phy_calibration = rtw8821a_phy_calibration, .cck_pd_set = rtw88xxa_phy_cck_pd_set, @@ -1175,6 +1176,7 @@ const struct rtw_chip_info rtw8821a_hw_spec = { .rfe_defs = rtw8821a_rfe_defs, .rfe_defs_size = ARRAY_SIZE(rtw8821a_rfe_defs), .rx_ldpc = false, + .amsdu_in_ampdu = true, .hw_feature_report = false, .c2h_ra_report_size = 4, .old_datarate_fb_limit = true, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821au.c b/drivers/net/wireless/realtek/rtw88/rtw8821au.c index a01744b64e8d..28c281b32978 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8821au.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8821au.c @@ -66,7 +66,7 @@ static const struct usb_device_id rtw_8821au_id_table[] = { MODULE_DEVICE_TABLE(usb, rtw_8821au_id_table); static struct usb_driver rtw_8821au_driver = { - .name = "rtw_8821au", + .name = KBUILD_MODNAME, .id_table = rtw_8821au_id_table, .probe = rtw_usb_probe, .disconnect = rtw_usb_disconnect, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.c b/drivers/net/wireless/realtek/rtw88/rtw8821c.c index 0ade7f11cbd2..413130a30ca9 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8821c.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.c @@ -1668,6 +1668,7 @@ static const struct rtw_chip_ops rtw8821c_ops = { .set_antenna = NULL, .set_tx_power_index = rtw8821c_set_tx_power_index, .cfg_ldo25 = rtw8821c_cfg_ldo25, + .set_ampdu_factor = NULL, .false_alarm_statistics = rtw8821c_false_alarm_statistics, .phy_calibration = rtw8821c_phy_calibration, .cck_pd_set = rtw8821c_phy_cck_pd_set, @@ -1990,6 +1991,7 @@ const struct rtw_chip_info rtw8821c_hw_spec = { .band = RTW_BAND_2G | RTW_BAND_5G, .page_size = TX_PAGE_SIZE, .dig_min = 0x1c, + .amsdu_in_ampdu = true, .usb_tx_agg_desc_num = 3, .hw_feature_report = true, .c2h_ra_report_size = 7, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821ce.c b/drivers/net/wireless/realtek/rtw88/rtw8821ce.c index f3d971feda04..40637c079d99 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8821ce.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8821ce.c @@ -21,7 +21,7 @@ static const struct pci_device_id rtw_8821ce_id_table[] = { MODULE_DEVICE_TABLE(pci, rtw_8821ce_id_table); static struct pci_driver rtw_8821ce_driver = { - .name = "rtw_8821ce", + .name = KBUILD_MODNAME, .id_table = rtw_8821ce_id_table, .probe = rtw_pci_probe, .remove = rtw_pci_remove, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821cs.c b/drivers/net/wireless/realtek/rtw88/rtw8821cs.c index a359413369a4..6d94162213c6 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8821cs.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8821cs.c @@ -20,7 +20,7 @@ static const struct sdio_device_id rtw_8821cs_id_table[] = { MODULE_DEVICE_TABLE(sdio, rtw_8821cs_id_table); static struct sdio_driver rtw_8821cs_driver = { - .name = "rtw_8821cs", + .name = KBUILD_MODNAME, .probe = rtw_sdio_probe, .remove = rtw_sdio_remove, .id_table = rtw_8821cs_id_table, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821cu.c b/drivers/net/wireless/realtek/rtw88/rtw8821cu.c index a019f4085e73..7a0fffc359e2 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8821cu.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8821cu.c @@ -48,7 +48,7 @@ static int rtw_8821cu_probe(struct usb_interface *intf, } static struct usb_driver rtw_8821cu_driver = { - .name = "rtw_8821cu", + .name = KBUILD_MODNAME, .id_table = rtw_8821cu_id_table, .probe = rtw_8821cu_probe, .disconnect = rtw_usb_disconnect, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c index b4934da88e33..ab199eaea3c7 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c @@ -2158,6 +2158,7 @@ static const struct rtw_chip_ops rtw8822b_ops = { .set_tx_power_index = rtw8822b_set_tx_power_index, .set_antenna = rtw8822b_set_antenna, .cfg_ldo25 = rtw8822b_cfg_ldo25, + .set_ampdu_factor = NULL, .false_alarm_statistics = rtw8822b_false_alarm_statistics, .phy_calibration = rtw8822b_phy_calibration, .pwr_track = rtw8822b_pwr_track, @@ -2531,6 +2532,7 @@ const struct rtw_chip_info rtw8822b_hw_spec = { .band = RTW_BAND_2G | RTW_BAND_5G, .page_size = TX_PAGE_SIZE, .dig_min = 0x1c, + .amsdu_in_ampdu = true, .usb_tx_agg_desc_num = 3, .hw_feature_report = true, .c2h_ra_report_size = 7, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822be.c b/drivers/net/wireless/realtek/rtw88/rtw8822be.c index 4994950776cd..0bb9f70e7920 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822be.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822be.c @@ -17,7 +17,7 @@ static const struct pci_device_id rtw_8822be_id_table[] = { MODULE_DEVICE_TABLE(pci, rtw_8822be_id_table); static struct pci_driver rtw_8822be_driver = { - .name = "rtw_8822be", + .name = KBUILD_MODNAME, .id_table = rtw_8822be_id_table, .probe = rtw_pci_probe, .remove = rtw_pci_remove, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822bs.c b/drivers/net/wireless/realtek/rtw88/rtw8822bs.c index 31d8645f83bd..744781dcb419 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822bs.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822bs.c @@ -20,7 +20,7 @@ static const struct sdio_device_id rtw_8822bs_id_table[] = { MODULE_DEVICE_TABLE(sdio, rtw_8822bs_id_table); static struct sdio_driver rtw_8822bs_driver = { - .name = "rtw_8822bs", + .name = KBUILD_MODNAME, .probe = rtw_sdio_probe, .remove = rtw_sdio_remove, .id_table = rtw_8822bs_id_table, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822bu.c b/drivers/net/wireless/realtek/rtw88/rtw8822bu.c index 572d1f31832e..44e28e583964 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822bu.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822bu.c @@ -77,6 +77,8 @@ static const struct usb_device_id rtw_8822bu_id_table[] = { .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Mercusys MA30N */ { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3322, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* D-Link DWA-T185 rev. A1 */ + { USB_DEVICE_AND_INTERFACE_INFO(0x0411, 0x03d1, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* BUFFALO WI-U2-866DM */ {}, }; MODULE_DEVICE_TABLE(usb, rtw_8822bu_id_table); @@ -88,7 +90,7 @@ static int rtw8822bu_probe(struct usb_interface *intf, } static struct usb_driver rtw_8822bu_driver = { - .name = "rtw_8822bu", + .name = KBUILD_MODNAME, .id_table = rtw_8822bu_id_table, .probe = rtw8822bu_probe, .disconnect = rtw_usb_disconnect, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c index 5e53e0db177e..017d959de3ce 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c @@ -3951,7 +3951,8 @@ static void rtw8822c_dpk_cal_coef1(struct rtw_dev *rtwdev) rtw_write32(rtwdev, REG_NCTL0, 0x00001148); rtw_write32(rtwdev, REG_NCTL0, 0x00001149); - check_hw_ready(rtwdev, 0x2d9c, MASKBYTE0, 0x55); + if (!check_hw_ready(rtwdev, 0x2d9c, MASKBYTE0, 0x55)) + rtw_warn(rtwdev, "DPK stuck, performance may be suboptimal"); rtw_write8(rtwdev, 0x1b10, 0x0); rtw_write32_mask(rtwdev, REG_NCTL0, BIT_SUBPAGE, 0x0000000c); @@ -4968,6 +4969,7 @@ static const struct rtw_chip_ops rtw8822c_ops = { .set_tx_power_index = rtw8822c_set_tx_power_index, .set_antenna = rtw8822c_set_antenna, .cfg_ldo25 = rtw8822c_cfg_ldo25, + .set_ampdu_factor = NULL, .false_alarm_statistics = rtw8822c_false_alarm_statistics, .dpk_track = rtw8822c_dpk_track, .phy_calibration = rtw8822c_phy_calibration, @@ -5349,6 +5351,7 @@ const struct rtw_chip_info rtw8822c_hw_spec = { .band = RTW_BAND_2G | RTW_BAND_5G, .page_size = TX_PAGE_SIZE, .dig_min = 0x20, + .amsdu_in_ampdu = true, .usb_tx_agg_desc_num = 3, .hw_feature_report = true, .c2h_ra_report_size = 7, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822ce.c b/drivers/net/wireless/realtek/rtw88/rtw8822ce.c index e26c6bc82936..9def732480af 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822ce.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822ce.c @@ -21,7 +21,7 @@ static const struct pci_device_id rtw_8822ce_id_table[] = { MODULE_DEVICE_TABLE(pci, rtw_8822ce_id_table); static struct pci_driver rtw_8822ce_driver = { - .name = "rtw_8822ce", + .name = KBUILD_MODNAME, .id_table = rtw_8822ce_id_table, .probe = rtw_pci_probe, .remove = rtw_pci_remove, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822cs.c b/drivers/net/wireless/realtek/rtw88/rtw8822cs.c index 975e81c824f2..322281e07eb8 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822cs.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822cs.c @@ -20,7 +20,7 @@ static const struct sdio_device_id rtw_8822cs_id_table[] = { MODULE_DEVICE_TABLE(sdio, rtw_8822cs_id_table); static struct sdio_driver rtw_8822cs_driver = { - .name = "rtw_8822cs", + .name = KBUILD_MODNAME, .probe = rtw_sdio_probe, .remove = rtw_sdio_remove, .id_table = rtw_8822cs_id_table, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822cu.c b/drivers/net/wireless/realtek/rtw88/rtw8822cu.c index 157d5102a4b1..324fd5c8bfd4 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822cu.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822cu.c @@ -32,7 +32,7 @@ static int rtw8822cu_probe(struct usb_interface *intf, } static struct usb_driver rtw_8822cu_driver = { - .name = "rtw_8822cu", + .name = KBUILD_MODNAME, .id_table = rtw_8822cu_id_table, .probe = rtw8822cu_probe, .disconnect = rtw_usb_disconnect, diff --git a/drivers/net/wireless/realtek/rtw88/sdio.c b/drivers/net/wireless/realtek/rtw88/sdio.c index 6209a49312f1..e733ed846123 100644 --- a/drivers/net/wireless/realtek/rtw88/sdio.c +++ b/drivers/net/wireless/realtek/rtw88/sdio.c @@ -10,6 +10,7 @@ #include <linux/mmc/host.h> #include <linux/mmc/sdio_func.h> #include "main.h" +#include "mac.h" #include "debug.h" #include "fw.h" #include "ps.h" @@ -677,12 +678,22 @@ static void rtw_sdio_enable_rx_aggregation(struct rtw_dev *rtwdev) { u8 size, timeout; - if (rtw_chip_wcpu_11n(rtwdev)) { + switch (rtwdev->chip->id) { + case RTW_CHIP_TYPE_8703B: + case RTW_CHIP_TYPE_8821A: + case RTW_CHIP_TYPE_8812A: size = 0x6; timeout = 0x6; - } else { + break; + case RTW_CHIP_TYPE_8723D: + size = 0xa; + timeout = 0x3; + rtw_write8_set(rtwdev, REG_RXDMA_AGG_PG_TH + 3, BIT(7)); + break; + default: size = 0xff; timeout = 0x1; + break; } /* Make the firmware honor the size limit configured below */ @@ -718,10 +729,7 @@ static u8 rtw_sdio_get_tx_qsel(struct rtw_dev *rtwdev, struct sk_buff *skb, case RTW_TX_QUEUE_H2C: return TX_DESC_QSEL_H2C; case RTW_TX_QUEUE_MGMT: - if (rtw_chip_wcpu_11n(rtwdev)) - return TX_DESC_QSEL_HIGH; - else - return TX_DESC_QSEL_MGMT; + return TX_DESC_QSEL_MGMT; case RTW_TX_QUEUE_HI0: return TX_DESC_QSEL_HIGH; default: @@ -1157,6 +1165,7 @@ static const struct rtw_hci_ops rtw_sdio_ops = { .link_ps = rtw_sdio_link_ps, .interface_cfg = rtw_sdio_interface_cfg, .dynamic_rx_agg = NULL, + .write_firmware_page = rtw_write_firmware_page, .read8 = rtw_sdio_read8, .read16 = rtw_sdio_read16, @@ -1227,10 +1236,7 @@ static void rtw_sdio_process_tx_queue(struct rtw_dev *rtwdev, return; } - if (queue <= RTW_TX_QUEUE_VO) - rtw_sdio_indicate_tx_status(rtwdev, skb); - else - dev_kfree_skb_any(skb); + rtw_sdio_indicate_tx_status(rtwdev, skb); } static void rtw_sdio_tx_handler(struct work_struct *work) @@ -1298,7 +1304,6 @@ static void rtw_sdio_deinit_tx(struct rtw_dev *rtwdev) struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv; int i; - flush_workqueue(rtwsdio->txwq); destroy_workqueue(rtwsdio->txwq); kfree(rtwsdio->tx_handler_data); diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c index c8092fa0d9f1..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: @@ -891,6 +946,7 @@ static const 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) |