From: Po-Hao Huang Improve user experience while using interactive applications. Adjust power saving decisions under different scenarios. Minimize latency for delay-sensitive connections by exiting power-save on packet bursts and maintain active until a period of inactivity is reached. For connections that are not that sensitive to delays, keep the current aggressive power save logic. Signed-off-by: Po-Hao Huang Signed-off-by: Ping-Ke Shih --- drivers/net/wireless/realtek/rtw89/core.c | 87 +++++++++++++++++++++-- drivers/net/wireless/realtek/rtw89/core.h | 9 +++ 2 files changed, 89 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index 70feab97dccb..c9c4ec1d93af 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -341,10 +341,26 @@ static const struct rtw89_hw_rate_def { }, }; +static void rtw89_core_tx_skb_proto_stats(struct rtw89_traffic_stats *stats, + struct sk_buff *skb) +{ + switch (ip_hdr(skb)->protocol) { + case IPPROTO_TCP: + stats->tcp++; + break; + case IPPROTO_UDP: + stats->udp++; + break; + default: + break; + } +} + static void __rtw89_traffic_stats_accu(struct rtw89_traffic_stats *stats, struct sk_buff *skb, bool tx) { if (tx) { + rtw89_core_tx_skb_proto_stats(stats, skb); stats->tx_cnt++; stats->tx_unicast += skb->len; } else { @@ -2902,6 +2918,23 @@ static void rtw89_core_bcn_track_reset(struct rtw89_dev *rtwdev) memset(&rtwdev->bcn_track, 0, sizeof(rtwdev->bcn_track)); } +static bool rtw89_core_proto_stats_can_lps(struct rtw89_dev *rtwdev, + struct rtw89_vif *rtwvif, + enum rtw89_tfc_interval interval) +{ + if (rtwdev->chip->chip_id != RTL8852A) + return true; + + if (rtwvif->burst_active) + return false; + + if (interval == RTW89_TFC_INTERVAL_100MS && + hweight8(rtwvif->stats_ps.active_histogram) < 3) + return false; + + return true; +} + static void rtw89_vif_rx_bcn_stat(struct rtw89_dev *rtwdev, struct sk_buff *skb) { #define RTW89_APPEND_TSF_2GHZ 384 @@ -4540,9 +4573,42 @@ static enum rtw89_tfc_lv rtw89_get_traffic_level(struct rtw89_dev *rtwdev, return RTW89_TFC_ULTRA_LOW; } +static void rtw89_calc_vif_active_histogram(struct rtw89_dev *rtwdev, + struct rtw89_traffic_stats *stats, + enum rtw89_tfc_interval interval) +{ + struct rtw89_vif *rtwvif; + + stats->udp_ratio = stats->tx_cnt ? + DIV_ROUND_DOWN_ULL(stats->udp * 100, stats->tx_cnt) : 0; + stats->active_histogram <<= 1; + + switch (interval) { + case RTW89_TFC_INTERVAL_2SEC: + rtwvif = container_of(stats, struct rtw89_vif, stats); + + if (stats->tcp >= RTW89_TCP_TH && stats->tx_cnt >= stats->rx_cnt) + stats->active_histogram |= BIT(0); + + if (stats->active_histogram & RTW89_RECENT_ACTIVE_HIST) + rtwvif->burst_active = true; + else + rtwvif->burst_active = false; + + break; + case RTW89_TFC_INTERVAL_100MS: + if (stats->udp_ratio >= RTW89_UDP_RATIO_TH) + stats->active_histogram |= BIT(0); + break; + } + + stats->tcp = 0; + stats->udp = 0; +} + static bool rtw89_traffic_stats_calc(struct rtw89_dev *rtwdev, struct rtw89_traffic_stats *stats, - enum rtw89_tfc_interval interval) + enum rtw89_tfc_interval interval, bool by_vif) { enum rtw89_tfc_lv tx_tfc_lv = stats->tx_tfc_lv; enum rtw89_tfc_lv rx_tfc_lv = stats->rx_tfc_lv; @@ -4564,6 +4630,9 @@ static bool rtw89_traffic_stats_calc(struct rtw89_dev *rtwdev, stats->rx_avg_len = stats->rx_cnt ? DIV_ROUND_DOWN_ULL(stats->rx_unicast, stats->rx_cnt) : 0; + if (by_vif) + rtw89_calc_vif_active_histogram(rtwdev, stats, interval); + stats->tx_unicast = 0; stats->rx_unicast = 0; stats->tx_cnt = 0; @@ -4585,11 +4654,11 @@ static bool rtw89_traffic_stats_track(struct rtw89_dev *rtwdev) bool tfc_changed; tfc_changed = rtw89_traffic_stats_calc(rtwdev, &rtwdev->stats, - RTW89_TFC_INTERVAL_2SEC); + RTW89_TFC_INTERVAL_2SEC, false); rtw89_for_each_rtwvif(rtwdev, rtwvif) { rtw89_traffic_stats_calc(rtwdev, &rtwvif->stats, - RTW89_TFC_INTERVAL_2SEC); + RTW89_TFC_INTERVAL_2SEC, true); rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) rtw89_fw_h2c_tp_offload(rtwdev, rtwvif_link); @@ -4598,7 +4667,8 @@ static bool rtw89_traffic_stats_track(struct rtw89_dev *rtwdev) return tfc_changed; } -static void rtw89_enter_lps_track(struct rtw89_dev *rtwdev) +static void rtw89_enter_lps_track(struct rtw89_dev *rtwdev, + enum rtw89_tfc_interval interval) { struct ieee80211_vif *vif; struct rtw89_vif *rtwvif; @@ -4622,6 +4692,9 @@ static void rtw89_enter_lps_track(struct rtw89_dev *rtwdev) if (!rtw89_core_bcn_track_can_lps(rtwdev)) continue; + if (!rtw89_core_proto_stats_can_lps(rtwdev, rtwvif, interval)) + continue; + rtw89_enter_lps(rtwdev, rtwvif, true); } } @@ -4771,13 +4844,13 @@ static void rtw89_track_ps_work(struct wiphy *wiphy, struct wiphy_work *work) rtw89_for_each_rtwvif(rtwdev, rtwvif) rtw89_traffic_stats_calc(rtwdev, &rtwvif->stats_ps, - RTW89_TFC_INTERVAL_100MS); + RTW89_TFC_INTERVAL_100MS, true); if (rtwdev->scanning) return; if (rtwdev->lps_enabled && !rtwdev->btc.lps) - rtw89_enter_lps_track(rtwdev); + rtw89_enter_lps_track(rtwdev, RTW89_TFC_INTERVAL_100MS); } static void rtw89_track_work(struct wiphy *wiphy, struct wiphy_work *work) @@ -4825,7 +4898,7 @@ static void rtw89_track_work(struct wiphy *wiphy, struct wiphy_work *work) rtw89_core_mlo_track(rtwdev); if (rtwdev->lps_enabled && !rtwdev->btc.lps) - rtw89_enter_lps_track(rtwdev); + rtw89_enter_lps_track(rtwdev, RTW89_TFC_INTERVAL_2SEC); } void rtw89_core_dm_disable_cfg(struct rtw89_dev *rtwdev, u32 new) diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index fd29dbbb120d..bbcac7cc207c 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -1477,6 +1477,10 @@ enum rtw89_tfc_lv { DECLARE_EWMA(tp, 10, 2); +#define RTW89_TCP_TH 40 +#define RTW89_UDP_RATIO_TH 70 +#define RTW89_RECENT_ACTIVE_HIST GENMASK(4, 0) + struct rtw89_traffic_stats { /* units in bytes */ u64 tx_unicast; @@ -1504,6 +1508,10 @@ struct rtw89_traffic_stats { u16 tx_rate; u16 rx_rate; + + /* used by rtwvif only */ + u64 tcp, udp, udp_ratio; + u8 active_histogram; }; struct rtw89_btc_chdef { @@ -6354,6 +6362,7 @@ struct rtw89_vif { struct rtw89_roc roc; bool offchan; + bool burst_active; enum rtw89_mlo_mode mlo_mode; struct rtw89_vif_ml_trans ml_trans; -- 2.25.1