From 9999ec48cadf1a6b25d608dbad8f7e66bbd2747d Mon Sep 17 00:00:00 2001
From: Nishant Pandey <nishpand@codeaurora.org>
Date: Sat, 28 Nov 2020 20:52:18 +0530
Subject: [PATCH] ath11k: Add power save state change and power_save_duration
 in the debugfs for each client.

This patch adds support to get the below power_save information
of each connected peer to AP. With WMI_PEER_STA_PS_STATECHG_EVENTID
event, below power save information is reported to user space via
debugfs.

Use the below commands in AP DUT to get the above power_save information.

To get the ps state of each sta:
cat /sys/kernel/debug/ieee80211/phyX/netdev::wlanX/stations/
XX:XX:XX:XX:XX:XX/peer_ps_state

If STA is in power save state, we get the peer_ps_state value as 1.
if STA is not in power save state, we get the peer_ps_state value as 0.
If ps_state event is disabled, we get the peer_ps_state value as 2.

We can enable/disable the ps_state events using the debugfs flag
"ps_state_enable"

echo Y > /sys/kernel/debug/ieee80211/phyX/ath11k/ps_state_enable

Y = 1 to enable and Y = 0 to disable
1.power_save_duration
2.time_since_station_in_power_save and
3.PS timekeeper to show a timeline about all PS state changes coming to AP,
with each event having information about MAC address of the peer connected,
Timestamp (real system time to milli seconds granularity) and
power save state.

To know the time_since_station_in_power_save:
cat /sys/kernel/debug/ieee80211/phyX/netdev:wlanX/stations/
XX:XX:XX:XX:XX:XX/current_ps_duration

To know power_save_duration:
cat /sys/kernel/debug/ieee80211/phyX/netdev:wlanX/stations/
XX:XX:XX:XX:XX:XX/total_ps_duration

To reset the power_save_duration of all stations connected to AP:
echo 1 > /sys/kernel/debug/ieee80211/phyX/ath11k/reset_ps_duration

To enable/disable the ps_timekeeper:
echo Y > /sys/kernel/debug/ieee80211/phyX/ath11k/ps_timekeeper_enable
Y = 1 to enable and Y = 0 to disable.

To record PS timekeeer logs after enabling ps_timekeeper:
trace-cmd record -e ath11k_ps_timekeeper

Signed-off-by: Nishant Pandey <nishpand@codeaurora.org>
---
 drivers/net/wireless/ath/ath11k/core.h        |  12 ++
 drivers/net/wireless/ath/ath11k/debugfs.c       | 215 ++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath11k/debugfs_sta.c | 106 +++++++++++++
 drivers/net/wireless/ath/ath11k/mac.c         |   1 +
 drivers/net/wireless/ath/ath11k/trace.h       |  25 +++
 drivers/net/wireless/ath/ath11k/wmi.c         |  82 ++++++++++
 drivers/net/wireless/ath/ath11k/wmi.h         |  21 +++
 7 files changed, 462 insertions(+)

Index: backports-20210222-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/core.h
===================================================================
--- backports-20210222-4.4.60-b157d2276.orig/drivers/net/wireless/ath/ath11k/core.h
+++ backports-20210222-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/core.h
@@ -424,6 +424,12 @@ struct ath11k_sta {
 	struct ath11k_nss_sta_stats *nss_stats;
 #endif
 	u16 tcl_metadata;
+	/* Protected with ar->data_lock */
+	u32 peer_ps_state;
+	u32 ps_start_time;
+	u32 ps_start_jiffies;
+	u8 peer_current_ps_valid;
+	u32 ps_total_duration;
 };
 
 #define ATH11K_MIN_5G_FREQ 4150
@@ -680,6 +686,11 @@ struct ath11k {
 	enum ath11k_ap_ps_state ap_ps_state;
 
 	bool monitor_vdev_created;
+
+	/* protected by conf_mutex */
+	u8 ps_state_enable;
+	u8 ps_timekeeper_enable;
+	u8 reset_ps_duration;
 };
 
 struct ath11k_band_cap {
Index: backports-20210222-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/debugfs.c
===================================================================
--- backports-20210222-4.4.60-b157d2276.orig/drivers/net/wireless/ath/ath11k/debugfs.c
+++ backports-20210222-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/debugfs.c
@@ -1782,6 +1782,207 @@ static const struct file_operations fops
 	.open = simple_open
 };
 
+static ssize_t ath11k_write_ps_timekeeper_enable(struct file *file,
+						 const char __user *user_buf,
+						 size_t count, loff_t *ppos)
+{
+	struct ath11k *ar = file->private_data;
+	ssize_t ret;
+	u8 ps_timekeeper_enable;
+
+	if (kstrtou8_from_user(user_buf, count, 0, &ps_timekeeper_enable))
+		return -EINVAL;
+
+	if (ps_timekeeper_enable > 1)
+		return -EINVAL;
+
+	mutex_lock(&ar->conf_mutex);
+
+	if (ar->state != ATH11K_STATE_ON) {
+		ret = -ENETDOWN;
+		goto exit;
+	}
+
+	if (!ar->ps_state_enable) {
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	if (ar->ps_timekeeper_enable == ps_timekeeper_enable) {
+		ret = count;
+		goto exit;
+	}
+
+	ar->ps_timekeeper_enable = ps_timekeeper_enable;
+	ret = count;
+exit:
+	mutex_unlock(&ar->conf_mutex);
+
+	return ret;
+}
+
+static ssize_t ath11k_read_ps_timekeeper_enable(struct file *file,
+						char __user *user_buf,
+						size_t count, loff_t *ppos)
+{
+	struct ath11k *ar = file->private_data;
+	int len = 0;
+	char buf[32];
+
+	mutex_lock(&ar->conf_mutex);
+	len = scnprintf(buf, sizeof(buf) - len, "%d\n",
+			ar->ps_timekeeper_enable);
+	mutex_unlock(&ar->conf_mutex);
+
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static const struct file_operations fops_ps_timekeeper_enable = {
+	.read = ath11k_read_ps_timekeeper_enable,
+	.write = ath11k_write_ps_timekeeper_enable,
+	.open = simple_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
+static void ath11k_reset_peer_ps_duration(void *data, struct ieee80211_sta *sta)
+{
+	struct ath11k *ar = data;
+	struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
+
+	spin_lock_bh(&ar->data_lock);
+	arsta->ps_total_duration = WMI_PEER_RESET_PS_DURATION;
+	spin_unlock_bh(&ar->data_lock);
+}
+
+static ssize_t ath11k_write_reset_ps_duration(struct file *file,
+					      const  char __user *user_buf,
+					      size_t count, loff_t *ppos)
+{
+	struct ath11k *ar = file->private_data;
+	int ret;
+	u8 reset_ps_duration;
+
+	if (kstrtou8_from_user(user_buf, count, 0, &reset_ps_duration))
+		return -EINVAL;
+
+	if (reset_ps_duration != 1)
+		return -EINVAL;
+
+	mutex_lock(&ar->conf_mutex);
+
+	if (ar->state != ATH11K_STATE_ON) {
+		ret = -ENETDOWN;
+		goto exit;
+	}
+
+	if (!ar->ps_state_enable) {
+		ret = -EINVAL;
+		goto exit;
+	}
+	ar->reset_ps_duration = reset_ps_duration;
+	ieee80211_iterate_stations_atomic(ar->hw,
+					  ath11k_reset_peer_ps_duration,
+					  ar);
+
+	ret = count;
+exit:
+	mutex_unlock(&ar->conf_mutex);
+	return ret;
+}
+
+static const struct file_operations fops_reset_ps_duration = {
+	.write = ath11k_write_reset_ps_duration,
+	.open = simple_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
+static void ath11k_peer_ps_state_disable(void *data,
+					 struct ieee80211_sta *sta)
+{
+	struct ath11k *ar = data;
+	struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
+
+	spin_lock_bh(&ar->data_lock);
+	arsta->peer_ps_state = WMI_PEER_PS_STATE_DISABLED;
+	arsta->ps_start_time = WMI_PEER_RESET_PS_TIME;
+	arsta->ps_total_duration = WMI_PEER_RESET_PS_DURATION;
+	spin_unlock_bh(&ar->data_lock);
+}
+
+static ssize_t ath11k_write_ps_state_enable(struct file *file,
+					    const char __user *user_buf,
+					    size_t count, loff_t *ppos)
+{
+	struct ath11k *ar = file->private_data;
+	struct ath11k_pdev *pdev = ar->pdev;
+	int ret;
+	u32 param;
+	u8 ps_state_enable;
+
+	if (kstrtou8_from_user(user_buf, count, 0, &ps_state_enable))
+		return -EINVAL;
+
+	if (ps_state_enable > 1 || ps_state_enable < 0)
+		return -EINVAL;
+
+	mutex_lock(&ar->conf_mutex);
+
+	if (ar->ps_state_enable == ps_state_enable) {
+		ret = count;
+		goto exit;
+	}
+
+	param = WMI_PDEV_PEER_STA_PS_STATECHG_ENABLE;
+	ret = ath11k_wmi_pdev_set_param(ar, param, ps_state_enable, pdev->pdev_id);
+	if (ret) {
+		ath11k_warn(ar, "failed to enable ps_state_enable: %d\n",
+			    ret);
+		goto exit;
+	}
+	ar->ps_state_enable = ps_state_enable;
+
+	if (!ar->ps_state_enable) {
+		ar->ps_timekeeper_enable = WMI_PEER_RESET_PS_TIME_KEEPER;
+		ieee80211_iterate_stations_atomic(ar->hw,
+						  ath11k_peer_ps_state_disable,
+						  ar);
+	}
+
+	ret = count;
+
+exit:
+	mutex_unlock(&ar->conf_mutex);
+
+	return ret;
+}
+
+static ssize_t ath11k_read_ps_state_enable(struct file *file,
+					   char __user *user_buf,
+					   size_t count, loff_t *ppos)
+{
+	struct ath11k *ar = file->private_data;
+	int len = 0;
+	char buf[32];
+
+	mutex_lock(&ar->conf_mutex);
+	len = scnprintf(buf, sizeof(buf) - len, "%d\n",
+			ar->ps_state_enable);
+	mutex_unlock(&ar->conf_mutex);
+
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static const struct file_operations fops_ps_state_enable = {
+	.read = ath11k_read_ps_state_enable,
+	.write = ath11k_write_ps_state_enable,
+	.open = simple_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
+
 static ssize_t ath11k_dump_mgmt_stats(struct file *file, char __user *ubuf,
 				      size_t count, loff_t *ppos)
 {
@@ -2651,6 +2852,20 @@ int ath11k_debugfs_register(struct ath11
 			    ar->debug.debugfs_pdev, ar,
 			    &fops_dump_mgmt_stats);
 
+	debugfs_create_file("ps_state_enable", 0600, ar->debug.debugfs_pdev, ar,
+			    &fops_ps_state_enable);
+
+	if (test_bit(WMI_TLV_SERVICE_PEER_POWER_SAVE_DURATION_SUPPORT,
+		     ar->ab->wmi_ab.svc_map)) {
+		debugfs_create_file("ps_timekeeper_enable", 0600,
+				    ar->debug.debugfs_pdev, ar,
+				    &fops_ps_timekeeper_enable);
+
+		debugfs_create_file("reset_ps_duration", 0200,
+				    ar->debug.debugfs_pdev, ar,
+				    &fops_reset_ps_duration);
+	}
+
 	if (ar->hw->wiphy->bands[NL80211_BAND_5GHZ]) {
 		debugfs_create_file("dfs_simulate_radar", 0200,
 				    ar->debug.debugfs_pdev, ar,
Index: backports-20210222-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/debugfs_sta.c
===================================================================
--- backports-20210222-4.4.60-b157d2276.orig/drivers/net/wireless/ath/ath11k/debugfs_sta.c
+++ backports-20210222-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/debugfs_sta.c
@@ -1096,11 +1096,117 @@ static const struct file_operations fops
 	.llseek = default_llseek,
 };
 
+static ssize_t ath11k_dbg_sta_read_peer_ps_state(struct file *file,
+						 char __user *user_buf,
+						 size_t count, loff_t *ppos)
+{
+	struct ieee80211_sta *sta = file->private_data;
+	struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
+	struct ath11k *ar = arsta->arvif->ar;
+	char buf[20];
+	int len = 0;
+
+	spin_lock_bh(&ar->data_lock);
+
+	len = scnprintf(buf, sizeof(buf) - len, "%d\n",
+			arsta->peer_ps_state);
+
+	spin_unlock_bh(&ar->data_lock);
+
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static const struct file_operations fops_peer_ps_state = {
+	.open = simple_open,
+	.read = ath11k_dbg_sta_read_peer_ps_state,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
+static ssize_t ath11k_dbg_sta_read_current_ps_duration(struct file *file,
+						       char __user *user_buf,
+						       size_t count,
+						       loff_t *ppos)
+{
+	struct ieee80211_sta *sta = file->private_data;
+	struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
+	struct ath11k *ar = arsta->arvif->ar;
+	u32 time_since_station_in_power_save;
+	char buf[20];
+	int len = 0;
+
+	spin_lock_bh(&ar->data_lock);
+
+	if (arsta->peer_ps_state == WMI_PEER_STA_PS_MODE && arsta->peer_current_ps_valid)
+		time_since_station_in_power_save = jiffies_to_msecs(jiffies
+						 - arsta->ps_start_jiffies);
+	else
+		time_since_station_in_power_save = 0;
+
+	len = scnprintf(buf, sizeof(buf) - len, "%d\n",
+			time_since_station_in_power_save);
+	spin_unlock_bh(&ar->data_lock);
+
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static const struct file_operations fops_current_ps_duration = {
+	.open = simple_open,
+	.read = ath11k_dbg_sta_read_current_ps_duration,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
+static ssize_t ath11k_dbg_sta_read_total_ps_duration(struct file *file,
+						     char __user *user_buf,
+						     size_t count, loff_t *ppos)
+{
+	struct ieee80211_sta *sta = file->private_data;
+	struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
+	struct ath11k *ar = arsta->arvif->ar;
+	char buf[20];
+	u32 power_save_duration;
+	int len = 0;
+
+	spin_lock_bh(&ar->data_lock);
+
+	if (arsta->peer_ps_state == WMI_PEER_STA_PS_MODE && arsta->peer_current_ps_valid)
+		power_save_duration = jiffies_to_msecs(jiffies
+						 - arsta->ps_start_jiffies)
+						 + arsta->ps_total_duration;
+	else
+		power_save_duration = arsta->ps_total_duration;
+
+	len = scnprintf(buf, sizeof(buf) - len, "%d\n",
+			power_save_duration);
+
+	spin_unlock_bh(&ar->data_lock);
+
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static const struct file_operations fops_total_ps_duration = {
+	.open = simple_open,
+	.read = ath11k_dbg_sta_read_total_ps_duration,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
 void ath11k_debugfs_sta_op_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 			       struct ieee80211_sta *sta, struct dentry *dir)
 {
 	struct ath11k *ar = hw->priv;
 
+	debugfs_create_file("peer_ps_state", 0400, dir, sta,
+			    &fops_peer_ps_state);
+
+	if (test_bit(WMI_TLV_SERVICE_PEER_POWER_SAVE_DURATION_SUPPORT,
+		     ar->ab->wmi_ab.svc_map)) {
+		debugfs_create_file("current_ps_duration", 0440, dir, sta,
+				    &fops_current_ps_duration);
+		debugfs_create_file("total_ps_duration", 0440, dir, sta,
+				    &fops_total_ps_duration);
+	}
 	if (ath11k_debugfs_is_extd_tx_stats_enabled(ar))
 		debugfs_create_file("tx_stats", 0400, dir, sta,
 				    &fops_tx_stats);
Index: backports-20210222-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/mac.c
===================================================================
--- backports-20210222-4.4.60-b157d2276.orig/drivers/net/wireless/ath/ath11k/mac.c
+++ backports-20210222-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/mac.c
@@ -4382,6 +4382,7 @@ static int ath11k_mac_op_sta_state(struc
 	    new_state == IEEE80211_STA_NONE) {
 		memset(arsta, 0, sizeof(*arsta));
 		arsta->arvif = arvif;
+		arsta->peer_ps_state = WMI_PEER_PS_STATE_DISABLED;
 		INIT_WORK(&arsta->update_wk, ath11k_sta_rc_update_wk);
 		INIT_WORK(&arsta->use_4addr_wk, ath11k_sta_use_4addr_wk);
 
Index: backports-20210222-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/trace.h
===================================================================
--- backports-20210222-4.4.60-b157d2276.orig/drivers/net/wireless/ath/ath11k/trace.h
+++ backports-20210222-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/trace.h
@@ -51,6 +51,31 @@ TRACE_EVENT(ath11k_htt_pktlog,
 	 )
 );
 
+TRACE_EVENT(ath11k_ps_timekeeper,
+	    TP_PROTO(struct ath11k *ar, void *peer_addr,
+		     u32 peer_ps_timestamp, u8 peer_ps_state),
+	    TP_ARGS(ar, peer_addr, peer_ps_timestamp, peer_ps_state),
+	    TP_STRUCT__entry(__string(device, dev_name(ar->ab->dev))
+			     __string(driver, dev_driver_string(ar->ab->dev))
+			     __dynamic_array(u8, peer_addr, ETH_ALEN)
+			     __field(u8, peer_ps_state)
+			     __field(u32, peer_ps_timestamp)
+	    ),
+	    TP_fast_assign(__assign_str(device, dev_name(ar->ab->dev));
+			   __assign_str(driver, dev_driver_string(ar->ab->dev));
+			   memcpy(__get_dynamic_array(peer_addr), peer_addr,
+				  ETH_ALEN);
+			   __entry->peer_ps_state = peer_ps_state;
+			   __entry->peer_ps_timestamp = peer_ps_timestamp;
+	    ),
+	    TP_printk("%s %s %u %u",
+		      __get_str(driver),
+		      __get_str(device),
+		      __entry->peer_ps_state,
+		      __entry->peer_ps_timestamp
+	    )
+);
+
 TRACE_EVENT(ath11k_htt_ppdu_stats,
 	    TP_PROTO(struct ath11k *ar, const void *data, size_t len),
 
Index: backports-20210222-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/wmi.c
===================================================================
--- backports-20210222-4.4.60-b157d2276.orig/drivers/net/wireless/ath/ath11k/wmi.c
+++ backports-20210222-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/wmi.c
@@ -8379,6 +8379,96 @@ static void ath11k_bcn_tx_status_event(s
 }
 
 
+void
+ath11k_wmi_event_peer_sta_ps_state_chg(struct ath11k_base *ab, struct sk_buff *skb)
+{
+	struct wmi_peer_sta_ps_state_chg_event *ev;
+	struct ieee80211_sta *sta;
+	struct ath11k_peer *peer;
+	struct ath11k *ar;
+	struct ath11k_sta *arsta;
+	u32 peer_previous_ps_state;
+	u8 peer_addr[ETH_ALEN];
+
+	ev = (struct wmi_peer_sta_ps_state_chg_event *)skb->data;
+	ether_addr_copy(peer_addr, ev->peer_macaddr.addr);
+
+	rcu_read_lock();
+
+	spin_lock_bh(&ab->base_lock);
+
+	peer = ath11k_peer_find_by_addr(ab, peer_addr);
+
+	if (!peer) {
+		ath11k_warn(ab, "peer not found %pM\n",
+			   peer_addr);
+
+
+		spin_unlock_bh(&ab->base_lock);
+		goto exit;
+	}
+
+	ar = ath11k_mac_get_ar_by_vdev_id(ab, peer->vdev_id);
+
+	if (!ar) {
+		ath11k_warn(ab, "invalid vdev id in peer sta ps state change ev %d",
+			    peer->vdev_id);
+
+		spin_unlock_bh(&ab->base_lock);
+		goto exit;
+	}
+
+	sta = peer->sta;
+
+	spin_unlock_bh(&ab->base_lock);
+
+	if (!sta) {
+		ath11k_warn(ab, "failed to find station entry %pM\n",
+			    peer_addr);
+		goto exit;
+	}
+
+	arsta = (struct ath11k_sta *)sta->drv_priv;
+
+	spin_lock_bh(&ar->data_lock);
+
+	peer_previous_ps_state = arsta->peer_ps_state;
+	arsta->peer_ps_state = ev->peer_ps_state;
+	arsta->peer_current_ps_valid = !WMI_PEER_CURRENT_VALID_PS_STATE;
+
+	if (test_bit(WMI_TLV_SERVICE_PEER_POWER_SAVE_DURATION_SUPPORT,
+		     ar->ab->wmi_ab.svc_map)) {
+		if (!(ev->ps_supported_bitmap & WMI_PEER_PS_VALID_SUPPORTED))
+			goto out;
+
+		if (!(ev->ps_supported_bitmap & WMI_PEER_PS_STATE_TIMESTAMP_SUPPORTED))
+			goto out;
+
+		if (!ev->peer_ps_valid)
+			goto out;
+
+		arsta->peer_current_ps_valid = WMI_PEER_CURRENT_VALID_PS_STATE;
+
+		if (arsta->peer_ps_state == WMI_PEER_STA_PS_MODE) {
+			arsta->ps_start_time = ev->peer_ps_timestamp;
+			arsta->ps_start_jiffies = jiffies;
+		} else if (!arsta->peer_ps_state && peer_previous_ps_state == WMI_PEER_STA_PS_MODE)
+			arsta->ps_total_duration = arsta->ps_total_duration +
+					   (ev->peer_ps_timestamp - arsta->ps_start_time);
+
+		if (ar->ps_timekeeper_enable)
+			trace_ath11k_ps_timekeeper(ar, peer_addr, ev->peer_ps_timestamp,
+						   arsta->peer_ps_state);
+
+	}
+
+out:
+	spin_unlock_bh(&ar->data_lock);
+
+exit:
+	rcu_read_unlock();
+}
+
 static void ath11k_wmi_wds_peer_event(struct ath11k_base *ab,
 				      struct sk_buff *skb)
 {
@@ -8552,6 +8642,9 @@ static void ath11k_wmi_tlv_op_rx(struct
 	case WMI_MUEDCA_PARAMS_CONFIG_EVENTID:
 		ath11k_wmi_pdev_update_muedca_params_status_event(ab, skb);
 		break;
+	case WMI_PEER_STA_PS_STATECHG_EVENTID:
+		ath11k_wmi_event_peer_sta_ps_state_chg(ab, skb);
+		break;
 	case WMI_DIAG_EVENTID:
 		ath11k_wmi_diag_event(ab, skb);
 		break;
Index: backports-20210222-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/wmi.h
===================================================================
--- backports-20210222-4.4.60-b157d2276.orig/drivers/net/wireless/ath/ath11k/wmi.h
+++ backports-20210222-4.4.60-b157d2276/drivers/net/wireless/ath/ath11k/wmi.h
@@ -5792,6 +5792,33 @@ struct wmi_qos_null_tx_cmd {
 #define WMI_SERVICE_READY_TIMEOUT_HZ (5 * HZ)
 #define WMI_SEND_TIMEOUT_HZ (3 * HZ)
 
+enum ath11k_wmi_peer_ps_param {
+	WMI_PEER_STA_WAKEUP_MODE = 0,
+	WMI_PEER_STA_PS_MODE = 1,
+	WMI_PEER_PS_STATE_DISABLED = 2,
+};
+
+#define	WMI_PEER_RESET_PS_TIME_KEEPER  0
+#define	WMI_PEER_RESET_PS_TIME  0
+#define	WMI_PEER_RESET_PS_DURATION  0
+#define	WMI_PEER_CURRENT_VALID_PS_STATE  1
+
+
+enum wmi_peer_ps_supported_bitmap {
+	/* Used to indicate that power save state change is valid */
+	WMI_PEER_PS_VALID_SUPPORTED = 0x00000001,
+	WMI_PEER_PS_STATE_TIMESTAMP_SUPPORTED = 0x00000002,
+};
+
+struct wmi_peer_sta_ps_state_chg_event {
+	u32 tlv_header;
+	struct wmi_mac_addr peer_macaddr;
+	u32 peer_ps_state;
+	u32 ps_supported_bitmap;
+	u32 peer_ps_valid;
+	u32 peer_ps_timestamp;
+} __packed;
+
 struct ath11k_wmi_base {
 	struct ath11k_base *ab;
 	struct ath11k_pdev_wmi wmi[MAX_RADIOS];
