Browse Source

qcacld-3.0: Add support to force power save on active MLO links

Add support to force power save on all the active MLO links
for a defined number of beacon periods. Force power save
allows the firmware to suspend STA links for X beacon
periods and remain asleep even if the AP advertises TIM as
opposed to regular power save mode where STA links wake up
if the AP indicates that it has buffered data to send.

Change-Id: I98251f84edeebc462703cb2ad7d9ef3f73b460a4
CRs-Fixed: 3507781
Gururaj Pandurangi 2 years ago
parent
commit
1deaec1954

+ 17 - 0
components/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h

@@ -1229,6 +1229,17 @@ bool policy_mgr_is_set_link_in_progress(struct wlan_objmgr_psoc *psoc);
  * Return: QDF_STATUS
  */
 QDF_STATUS policy_mgr_wait_for_set_link_update(struct wlan_objmgr_psoc *psoc);
+
+/**
+ * policy_mgr_get_active_vdev_bitmap() - to get active ML STA vdev bitmap
+ * @psoc: PSOC object information
+ *
+ * This API will fetch the active ML STA vdev bitmap.
+ *
+ * Return: vdev bitmap value
+ */
+uint32_t
+policy_mgr_get_active_vdev_bitmap(struct wlan_objmgr_psoc *psoc);
 #else
 static inline bool
 policy_mgr_is_ml_vdev_id(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
@@ -1270,6 +1281,12 @@ policy_mgr_wait_for_set_link_update(struct wlan_objmgr_psoc *psoc)
 {
 	return QDF_STATUS_E_NOSUPPORT;
 }
+
+static inline uint32_t
+policy_mgr_get_active_vdev_bitmap(struct wlan_objmgr_psoc *psoc)
+{
+	return 0;
+}
 #endif
 
 /**

+ 20 - 0
components/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c

@@ -5447,6 +5447,23 @@ policy_mgr_validate_set_mlo_link_cb(struct wlan_objmgr_psoc *psoc,
 							   param->reason);
 }
 
+uint32_t
+policy_mgr_get_active_vdev_bitmap(struct wlan_objmgr_psoc *psoc)
+{
+	struct policy_mgr_psoc_priv_obj *pm_ctx;
+
+	pm_ctx = policy_mgr_get_context(psoc);
+	if (!pm_ctx) {
+		policy_mgr_err("Invalid Context");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	policy_mgr_debug("active link bitmap value: %d",
+			 pm_ctx->active_vdev_bitmap);
+
+	return pm_ctx->active_vdev_bitmap;
+}
+
 /**
  * policy_mgr_mlo_sta_set_link_ext() - Set links for MLO STA
  * @psoc: psoc object
@@ -5519,6 +5536,9 @@ policy_mgr_mlo_sta_set_link_ext(struct wlan_objmgr_psoc *psoc,
 	policy_mgr_fill_ml_active_link_vdev_bitmap(req, mlo_vdev_lst,
 						   num_mlo_vdev);
 
+	pm_ctx->active_vdev_bitmap = req->param.vdev_bitmap[0];
+	pm_ctx->inactive_vdev_bitmap = req->param.vdev_bitmap[1];
+
 	if (mode == MLO_LINK_FORCE_MODE_ACTIVE_INACTIVE)
 		policy_mgr_fill_ml_inactive_link_vdev_bitmap(
 			req, mlo_inactive_vdev_lst, num_mlo_inactive_vdev);

+ 4 - 0
components/cmn_services/policy_mgr/src/wlan_policy_mgr_i.h

@@ -379,6 +379,8 @@ struct policy_mgr_cfg {
  * @dynamic_dfs_master_disabled: current state of dynamic dfs master
  * @set_link_in_progress: To track if set link is in progress
  * @set_link_update_done_evt: qdf event to synchronize set link
+ * @active_vdev_bitmap: Active vdev id bitmap
+ * @inactive_vdev_bitmap: Inactive vdev id bitmap
  * @restriction_mask:
  */
 struct policy_mgr_psoc_priv_obj {
@@ -427,6 +429,8 @@ struct policy_mgr_psoc_priv_obj {
 	bool set_link_in_progress;
 	qdf_event_t set_link_update_done_evt;
 #endif
+	uint32_t active_vdev_bitmap;
+	uint32_t inactive_vdev_bitmap;
 #ifdef FEATURE_WLAN_CH_AVOID_EXT
 	uint32_t restriction_mask;
 #endif

+ 10 - 0
core/mac/inc/sir_api.h

@@ -4319,6 +4319,16 @@ struct sme_sta_inactivity_timeout {
 	uint32_t sta_inactivity_timeout;
 };
 
+/**
+ * struct sme_vdev_pause - Pause vdev for a defined time interval
+ * @session_id: Session id
+ * @vdev_pause_duration: vdev pause duration
+ */
+struct sme_vdev_pause {
+	uint8_t session_id;
+	uint8_t vdev_pause_duration;
+};
+
 /*
  * struct wow_pulse_mode - WoW Pulse set cmd struct
  * @wow_pulse_enable: enable or disable this feature

+ 3 - 2
core/mac/inc/wni_api.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -237,7 +237,8 @@ enum eWniMsgTypes {
 	CM_ABORT_CONN_TIMER = SIR_SME_MSG_TYPES_BEGIN + 177,
 	WIFI_POS_PASN_PEER_DELETE_ALL = SIR_SME_MSG_TYPES_BEGIN + 178,
 	eWNI_SME_CHAN_INFO_EVENT = SIR_SME_MSG_TYPES_BEGIN + 179,
-	eWNI_SME_MSG_TYPES_END = SIR_SME_MSG_TYPES_BEGIN + 180
+	eWNI_SME_MSG_TYPES_END = SIR_SME_MSG_TYPES_BEGIN + 180,
+	eWNI_SME_VDEV_PAUSE_IND = SIR_SME_MSG_TYPES_BEGIN + 181
 };
 
 typedef struct sAniCfgTxRateCtrs {

+ 1 - 0
core/mac/src/pe/lim/lim_process_message_queue.c

@@ -1767,6 +1767,7 @@ static void lim_process_messages(struct mac_context *mac_ctx,
 	case WNI_SME_UPDATE_MU_EDCA_PARAMS:
 	case eWNI_SME_UPDATE_SESSION_EDCA_TXQ_PARAMS:
 	case WNI_SME_CFG_ACTION_FRM_HE_TB_PPDU:
+	case eWNI_SME_VDEV_PAUSE_IND:
 		/* These messages are from HDD.No need to respond to HDD */
 		lim_process_normal_hdd_msg(mac_ctx, msg, false);
 		break;

+ 34 - 0
core/mac/src/pe/lim/lim_process_sme_req_messages.c

@@ -7507,6 +7507,36 @@ lim_process_sme_cfg_action_frm_in_tb_ppdu(struct mac_context *mac_ctx,
 	lim_send_action_frm_tb_ppdu_cfg(mac_ctx, msg->vdev_id, msg->cfg);
 }
 
+static void
+lim_process_sme_send_vdev_pause(struct mac_context *mac_ctx,
+				struct sme_vdev_pause *msg)
+{
+	struct pe_session *session;
+	uint16_t vdev_pause_dur_ms;
+
+	if (!msg) {
+		pe_err("Buffer is NULL");
+		return;
+	}
+
+	session = pe_find_session_by_vdev_id(mac_ctx, msg->session_id);
+	if (!session) {
+		pe_warn("Session does not exist for given BSSID");
+		return;
+	}
+
+	if (!(wlan_vdev_mlme_get_opmode(session->vdev) == QDF_STA_MODE) &&
+	    wlan_vdev_mlme_is_mlo_vdev(session->vdev)) {
+		pe_err("vdev is not ML STA");
+		return;
+	}
+
+	vdev_pause_dur_ms = session->beaconParams.beaconInterval *
+						msg->vdev_pause_duration;
+	wlan_mlo_send_vdev_pause(mac_ctx->psoc, session->vdev,
+				 msg->session_id, vdev_pause_dur_ms);
+}
+
 static void lim_process_sme_update_config(struct mac_context *mac_ctx,
 					  struct update_config *msg)
 {
@@ -8625,6 +8655,10 @@ bool lim_process_sme_req_messages(struct mac_context *mac,
 		lim_process_sme_cfg_action_frm_in_tb_ppdu(mac,
 				(struct  sir_cfg_action_frm_tb_ppdu *)msg_buf);
 		break;
+	case eWNI_SME_VDEV_PAUSE_IND:
+		lim_process_sme_send_vdev_pause(mac,
+					(struct sme_vdev_pause *)msg_buf);
+		break;
 	default:
 		qdf_mem_free((void *)pMsg->bodyptr);
 		pMsg->bodyptr = NULL;

+ 19 - 0
core/sme/inc/sme_api.h

@@ -3758,6 +3758,17 @@ void sme_activate_mlo_links(mac_handle_t mac_handle, uint8_t session_id,
 int sme_update_eht_caps(mac_handle_t mac_handle, uint8_t session_id,
 			uint8_t cfg_val, enum sme_eht_tx_bfee_cap_type cap_type,
 			enum QDF_OPMODE op_mode);
+/**
+ * sme_send_vdev_pause_for_bcn_period() - Send vdev pause indication to FW
+ * @mac_handle: Opaque handle to the global MAC context
+ * @session_id: SME session id
+ * @cfg_val: Set vdev pause duration
+ *
+ * Return: 0 on success otherwise error code
+ */
+int sme_send_vdev_pause_for_bcn_period(mac_handle_t mac_handle,
+				       uint8_t session_id,
+				       uint8_t cfg_val);
 #else
 static inline void sme_set_eht_testbed_def(mac_handle_t mac_handle,
 					   uint8_t vdev_id)
@@ -3794,6 +3805,14 @@ int sme_update_eht_caps(mac_handle_t mac_handle, uint8_t session_id,
 {
 	return 0;
 }
+
+static inline
+int sme_send_vdev_pause_for_bcn_period(mac_handle_t mac_handle,
+				       uint8_t session_id,
+				       uint8_t cfg_val)
+{
+	return 0;
+}
 #endif
 
 /**

+ 30 - 0
core/sme/src/common/sme_api.c

@@ -15327,6 +15327,36 @@ int sme_update_eht_caps(mac_handle_t mac_handle, uint8_t session_id,
 
 	return 0;
 }
+
+int
+sme_send_vdev_pause_for_bcn_period(mac_handle_t mac_handle, uint8_t session_id,
+				   uint8_t cfg_val)
+{
+	struct sme_vdev_pause *vdev_pause;
+	struct scheduler_msg msg = {0};
+	QDF_STATUS status;
+
+	vdev_pause = qdf_mem_malloc(sizeof(*vdev_pause));
+	if (!vdev_pause)
+		return -EIO;
+
+	vdev_pause->session_id = session_id;
+	vdev_pause->vdev_pause_duration = cfg_val;
+	qdf_mem_zero(&msg, sizeof(msg));
+	msg.type = eWNI_SME_VDEV_PAUSE_IND;
+	msg.reserved = 0;
+	msg.bodyptr = vdev_pause;
+	status = scheduler_post_message(QDF_MODULE_ID_SME,
+					QDF_MODULE_ID_PE,
+					QDF_MODULE_ID_PE, &msg);
+	if (status != QDF_STATUS_SUCCESS) {
+		sme_err("Not able to post vdev pause indication");
+		qdf_mem_free(vdev_pause);
+		return -EIO;
+	}
+
+	return 0;
+}
 #endif
 
 void sme_set_nss_capability(mac_handle_t mac_handle, uint8_t vdev_id,