mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 10:09:10 +02:00
wifi: rtw89: 8852a: refine power save to lower latency
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 <phhuang@realtek.com> Signed-off-by: Ping-Ke Shih <pkshih@realtek.com> Link: https://patch.msgid.link/20260420034051.17666-3-pkshih@realtek.com
This commit is contained in:
parent
d6a3aac6ed
commit
fdf0eb3551
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user