diff options
Diffstat (limited to 'drivers/net/wireless/realtek/rtw88/main.c')
-rw-r--r-- | drivers/net/wireless/realtek/rtw88/main.c | 129 |
1 files changed, 79 insertions, 50 deletions
diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c index 6d22628129d0..0cee0fd8c0ef 100644 --- a/drivers/net/wireless/realtek/rtw88/main.c +++ b/drivers/net/wireless/realtek/rtw88/main.c @@ -19,6 +19,7 @@ #include "bf.h" #include "sar.h" #include "sdio.h" +#include "led.h" bool rtw_disable_lps_deep_mode; EXPORT_SYMBOL(rtw_disable_lps_deep_mode); @@ -202,6 +203,21 @@ static void rtw_vif_watch_dog_iter(void *data, struct ieee80211_vif *vif) rtwvif->stats.rx_cnt = 0; } +static void rtw_sw_beacon_loss_check(struct rtw_dev *rtwdev, + struct rtw_vif *rtwvif, int received_beacons) +{ + int watchdog_delay = 2000000 / 1024; /* TU */ + int beacon_int, expected_beacons; + + if (rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_BCN_FILTER) || !rtwvif) + return; + + beacon_int = rtwvif_to_vif(rtwvif)->bss_conf.beacon_int; + expected_beacons = DIV_ROUND_UP(watchdog_delay, beacon_int); + + rtwdev->beacon_loss = received_beacons < expected_beacons / 2; +} + /* process TX/RX statistics periodically for hardware, * the information helps hardware to enhance performance */ @@ -212,6 +228,8 @@ static void rtw_watch_dog_work(struct work_struct *work) struct rtw_traffic_stats *stats = &rtwdev->stats; struct rtw_watch_dog_iter_data data = {}; bool busy_traffic = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags); + int received_beacons = rtwdev->dm_info.cur_pkt_count.num_bcn_pkt; + u32 tx_unicast_mbps, rx_unicast_mbps; bool ps_active; mutex_lock(&rtwdev->mutex); @@ -227,9 +245,6 @@ static void rtw_watch_dog_work(struct work_struct *work) else clear_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags); - rtw_coex_wl_status_check(rtwdev); - rtw_coex_query_bt_hid_list(rtwdev); - if (busy_traffic != test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags)) rtw_coex_wl_status_change_notify(rtwdev, 0); @@ -239,10 +254,11 @@ static void rtw_watch_dog_work(struct work_struct *work) else ps_active = false; - ewma_tp_add(&stats->tx_ewma_tp, - (u32)(stats->tx_unicast >> RTW_TP_SHIFT)); - ewma_tp_add(&stats->rx_ewma_tp, - (u32)(stats->rx_unicast >> RTW_TP_SHIFT)); + tx_unicast_mbps = stats->tx_unicast >> RTW_TP_SHIFT; + rx_unicast_mbps = stats->rx_unicast >> RTW_TP_SHIFT; + + ewma_tp_add(&stats->tx_ewma_tp, tx_unicast_mbps); + ewma_tp_add(&stats->rx_ewma_tp, rx_unicast_mbps); stats->tx_throughput = ewma_tp_read(&stats->tx_ewma_tp); stats->rx_throughput = ewma_tp_read(&stats->rx_ewma_tp); @@ -257,15 +273,23 @@ static void rtw_watch_dog_work(struct work_struct *work) /* make sure BB/RF is working for dynamic mech */ rtw_leave_lps(rtwdev); + rtw_coex_wl_status_check(rtwdev); + rtw_coex_query_bt_hid_list(rtwdev); + rtw_coex_active_query_bt_info(rtwdev); rtw_phy_dynamic_mechanism(rtwdev); + rtw_hci_dynamic_rx_agg(rtwdev, + tx_unicast_mbps >= 1 || rx_unicast_mbps >= 1); + data.rtwdev = rtwdev; /* rtw_iterate_vifs internally uses an atomic iterator which is needed * to avoid taking local->iflist_mtx mutex */ rtw_iterate_vifs(rtwdev, rtw_vif_watch_dog_iter, &data); + rtw_sw_beacon_loss_check(rtwdev, data.rtwvif, received_beacons); + /* fw supports only one station associated to enter lps, if there are * more than two stations associated to the AP, then we can not enter * lps, because fw does not handle the overlapped beacon interval @@ -307,17 +331,6 @@ static void rtw_ips_work(struct work_struct *work) mutex_unlock(&rtwdev->mutex); } -static u8 rtw_acquire_macid(struct rtw_dev *rtwdev) -{ - unsigned long mac_id; - - mac_id = find_first_zero_bit(rtwdev->mac_id_map, RTW_MAX_MAC_ID_NUM); - if (mac_id < RTW_MAX_MAC_ID_NUM) - set_bit(mac_id, rtwdev->mac_id_map); - - return mac_id; -} - static void rtw_sta_rc_work(struct work_struct *work) { struct rtw_sta_info *si = container_of(work, struct rtw_sta_info, @@ -336,12 +349,14 @@ int rtw_sta_add(struct rtw_dev *rtwdev, struct ieee80211_sta *sta, struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv; int i; - si->mac_id = rtw_acquire_macid(rtwdev); - if (si->mac_id >= RTW_MAX_MAC_ID_NUM) - return -ENOSPC; + if (vif->type == NL80211_IFTYPE_STATION) { + si->mac_id = rtwvif->mac_id; + } else { + si->mac_id = rtw_acquire_macid(rtwdev); + if (si->mac_id >= RTW_MAX_MAC_ID_NUM) + return -ENOSPC; + } - if (vif->type == NL80211_IFTYPE_STATION && vif->cfg.assoc == 0) - rtwvif->mac_id = si->mac_id; si->rtwdev = rtwdev; si->sta = sta; si->vif = vif; @@ -366,11 +381,13 @@ void rtw_sta_remove(struct rtw_dev *rtwdev, struct ieee80211_sta *sta, bool fw_exist) { struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv; + struct ieee80211_vif *vif = si->vif; int i; cancel_work_sync(&si->rc_work); - rtw_release_macid(rtwdev, si->mac_id); + if (vif->type != NL80211_IFTYPE_STATION) + rtw_release_macid(rtwdev, si->mac_id); if (fw_exist) rtw_fw_media_status_report(rtwdev, si->mac_id, false); @@ -610,6 +627,8 @@ static void rtw_reset_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) rtw_bf_disassoc(rtwdev, vif, NULL); rtw_vif_assoc_changed(rtwvif, NULL); rtw_txq_cleanup(rtwdev, vif->txq); + + rtw_release_macid(rtwdev, rtwvif->mac_id); } void rtw_fw_recovery(struct rtw_dev *rtwdev) @@ -1199,7 +1218,6 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si, u8 wireless_set; u8 bw_mode; u8 rate_id; - u8 rf_type = RF_1T1R; u8 stbc_en = 0; u8 ldpc_en = 0; u8 tx_num = 1; @@ -1284,13 +1302,10 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si, break; } - if (sta->deflink.vht_cap.vht_supported && ra_mask & 0xffc00000) { + if (sta->deflink.vht_cap.vht_supported && ra_mask & 0xffc00000) tx_num = 2; - rf_type = RF_2T2R; - } else if (sta->deflink.ht_cap.ht_supported && ra_mask & 0xfff00000) { + else if (sta->deflink.ht_cap.ht_supported && ra_mask & 0xfff00000) tx_num = 2; - rf_type = RF_2T2R; - } rate_id = get_rate_id(wireless_set, bw_mode, tx_num); @@ -1301,7 +1316,6 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si, si->bw_mode = bw_mode; si->stbc_en = stbc_en; si->ldpc_en = ldpc_en; - si->rf_type = rf_type; si->sgi_enable = is_support_sgi; si->vht_enable = is_vht_enable; si->ra_mask = ra_mask; @@ -1310,25 +1324,27 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si, rtw_fw_send_ra_info(rtwdev, si, reset_ra_mask); } -static int rtw_wait_firmware_completion(struct rtw_dev *rtwdev) +int rtw_wait_firmware_completion(struct rtw_dev *rtwdev) { const struct rtw_chip_info *chip = rtwdev->chip; struct rtw_fw_state *fw; + int ret = 0; fw = &rtwdev->fw; wait_for_completion(&fw->completion); if (!fw->firmware) - return -EINVAL; + ret = -EINVAL; if (chip->wow_fw_name) { fw = &rtwdev->wow_fw; wait_for_completion(&fw->completion); if (!fw->firmware) - return -EINVAL; + ret = -EINVAL; } - return 0; + return ret; } +EXPORT_SYMBOL(rtw_wait_firmware_completion); static enum rtw_lps_deep_mode rtw_update_lps_deep_mode(struct rtw_dev *rtwdev, struct rtw_fw_state *fw) @@ -1350,7 +1366,7 @@ static enum rtw_lps_deep_mode rtw_update_lps_deep_mode(struct rtw_dev *rtwdev, return LPS_DEEP_MODE_NONE; } -static int rtw_power_on(struct rtw_dev *rtwdev) +int rtw_power_on(struct rtw_dev *rtwdev) { const struct rtw_chip_info *chip = rtwdev->chip; struct rtw_fw_state *fw = &rtwdev->fw; @@ -1413,6 +1429,7 @@ err_off: err: return ret; } +EXPORT_SYMBOL(rtw_power_on); void rtw_core_fw_scan_notify(struct rtw_dev *rtwdev, bool start) { @@ -1485,7 +1502,7 @@ int rtw_core_start(struct rtw_dev *rtwdev) { int ret; - ret = rtw_power_on(rtwdev); + ret = rtwdev->chip->ops->power_on(rtwdev); if (ret) return ret; @@ -1505,12 +1522,13 @@ int rtw_core_start(struct rtw_dev *rtwdev) return 0; } -static void rtw_power_off(struct rtw_dev *rtwdev) +void rtw_power_off(struct rtw_dev *rtwdev) { rtw_hci_stop(rtwdev); rtw_coex_power_off_setting(rtwdev); rtw_mac_power_off(rtwdev); } +EXPORT_SYMBOL(rtw_power_off); void rtw_core_stop(struct rtw_dev *rtwdev) { @@ -1535,7 +1553,7 @@ void rtw_core_stop(struct rtw_dev *rtwdev) mutex_lock(&rtwdev->mutex); - rtw_power_off(rtwdev); + rtwdev->chip->ops->power_off(rtwdev); } static void rtw_init_ht_cap(struct rtw_dev *rtwdev, @@ -1917,6 +1935,9 @@ static int rtw_dump_hw_feature(struct rtw_dev *rtwdev) u8 bw; int i; + if (!rtwdev->chip->hw_feature_report) + return 0; + id = rtw_read8(rtwdev, REG_C2HEVT); if (id != C2H_HW_FEATURE_REPORT) { rtw_err(rtwdev, "failed to read hw feature report\n"); @@ -2006,7 +2027,7 @@ static int rtw_chip_efuse_info_setup(struct rtw_dev *rtwdev) efuse->ext_pa_2g = efuse->pa_type_2g & BIT(4) ? 1 : 0; efuse->ext_lna_2g = efuse->lna_type_2g & BIT(3) ? 1 : 0; efuse->ext_pa_5g = efuse->pa_type_5g & BIT(0) ? 1 : 0; - efuse->ext_lna_2g = efuse->lna_type_5g & BIT(3) ? 1 : 0; + efuse->ext_lna_5g = efuse->lna_type_5g & BIT(3) ? 1 : 0; if (!is_valid_ether_addr(efuse->addr)) { eth_random_addr(efuse->addr); @@ -2032,8 +2053,6 @@ static int rtw_chip_board_info_setup(struct rtw_dev *rtwdev) rtw_phy_setup_phy_cond(rtwdev, hal->pkg_type); rtw_phy_init_tx_power(rtwdev); - if (rfe_def->agc_btg_tbl) - rtw_load_table(rtwdev, rfe_def->agc_btg_tbl); rtw_load_table(rtwdev, rfe_def->phy_pg_tbl); rtw_load_table(rtwdev, rfe_def->txpwr_lmt_tbl); rtw_phy_tx_power_by_rate_config(hal); @@ -2136,7 +2155,6 @@ int rtw_core_init(struct rtw_dev *rtwdev) rtwdev->sec.total_cam_num = 32; rtwdev->hal.current_channel = 1; rtwdev->dm_info.fix_rate = U8_MAX; - set_bit(RTW_BC_MC_MACID, rtwdev->mac_id_map); rtw_stats_init(rtwdev); @@ -2206,6 +2224,7 @@ EXPORT_SYMBOL(rtw_core_deinit); int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw) { + bool sta_mode_only = rtwdev->hci.type == RTW_HCI_TYPE_SDIO; struct rtw_hal *hal = &rtwdev->hal; int max_tx_headroom = 0; int ret; @@ -2234,10 +2253,12 @@ int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw) ieee80211_hw_set(hw, TX_AMSDU); ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS); - hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_AP) | - BIT(NL80211_IFTYPE_ADHOC) | - BIT(NL80211_IFTYPE_MESH_POINT); + if (sta_mode_only) + hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); + else + hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_ADHOC); hw->wiphy->available_antennas_tx = hal->antenna_tx; hw->wiphy->available_antennas_rx = hal->antenna_rx; @@ -2248,7 +2269,7 @@ int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw) hw->wiphy->max_scan_ssids = RTW_SCAN_MAX_SSIDS; hw->wiphy->max_scan_ie_len = rtw_get_max_scan_ie_len(rtwdev); - if (rtwdev->chip->id == RTW_CHIP_TYPE_8822C) { + if (!sta_mode_only && rtwdev->chip->id == RTW_CHIP_TYPE_8822C) { hw->wiphy->iface_combinations = rtw_iface_combs; hw->wiphy->n_iface_combinations = ARRAY_SIZE(rtw_iface_combs); } @@ -2272,16 +2293,18 @@ int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw) return ret; } + rtw_led_init(rtwdev); + ret = ieee80211_register_hw(hw); if (ret) { rtw_err(rtwdev, "failed to register hw\n"); - return ret; + goto led_deinit; } ret = rtw_regd_hint(rtwdev); if (ret) { rtw_err(rtwdev, "failed to hint regd\n"); - return ret; + goto led_deinit; } rtw_debugfs_init(rtwdev); @@ -2290,6 +2313,10 @@ int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw) rtwdev->bf_info.bfer_su_cnt = 0; return 0; + +led_deinit: + rtw_led_deinit(rtwdev); + return ret; } EXPORT_SYMBOL(rtw_register_hw); @@ -2299,6 +2326,8 @@ void rtw_unregister_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw) ieee80211_unregister_hw(hw); rtw_unset_supported_band(hw, chip); + rtw_debugfs_deinit(rtwdev); + rtw_led_deinit(rtwdev); } EXPORT_SYMBOL(rtw_unregister_hw); |