Kaynağa Gözat

qcacld-3.0: Add support for changing LISTEN interval dynamically

Current method for calculating LISTEN INTERVAL are static
configuration a.ka. ini based. Now OEM / USER want to take
control of setting LISTEN INTERVAL as per their applications
need. Once if USER configure the LISTEN INTERVAL value using
vendor command then host should avoid changing the LI value
during each suspend/resume. User LI value will be override
configuration. Once USER will Disable the LI using vendor
command then host can fallback to current default method.

Change-Id: Ia9b412b073c059df0cdff7bcda8198f7581e796d
CRs-Fixed: 2040298
Mukul Sharma 8 yıl önce
ebeveyn
işleme
6398b253fb

+ 14 - 1
core/hdd/src/wlan_hdd_cfg80211.c

@@ -5426,6 +5426,7 @@ wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = {
 		.type = NLA_UNSPEC,
 		.len = QDF_MAC_ADDR_SIZE},
 	[RX_BLOCKSIZE_WINLIMIT] = {.type = NLA_U32},
+	[QCA_WLAN_VENDOR_ATTR_CONFIG_LISTEN_INTERVAL] = {.type = NLA_U32 },
 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_ENA] = {.type = NLA_U32 },
 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_CHAIN] = {.type = NLA_U32 },
 	[QCA_WLAN_VENDOR_ATTR_CONFIG_ANT_DIV_SELFTEST] = {.type = NLA_U32 },
@@ -5735,7 +5736,7 @@ __wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
 	struct hdd_context *hdd_ctx  = wiphy_priv(wiphy);
 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
 	int ret_val = 0;
-	u32 modulated_dtim;
+	u32 modulated_dtim, override_li;
 	u16 stats_avg_factor;
 	u32 guard_time;
 	uint8_t set_value;
@@ -5802,6 +5803,18 @@ __wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
 			ret_val = -EPERM;
 	}
 
+	if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_LISTEN_INTERVAL]) {
+		override_li = nla_get_u32(
+			tb[QCA_WLAN_VENDOR_ATTR_CONFIG_LISTEN_INTERVAL]);
+
+		status = sme_override_listen_interval(hdd_ctx->hHal,
+						      adapter->sessionId,
+						      override_li);
+
+		if (status != QDF_STATUS_SUCCESS)
+			ret_val = -EPERM;
+	}
+
 	if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]) {
 		qpower = nla_get_u8(
 			tb[QCA_WLAN_VENDOR_ATTR_CONFIG_QPOWER]);

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

@@ -960,6 +960,9 @@ QDF_STATUS sme_ext_change_channel(tHalHandle hHal, uint32_t channel,
 QDF_STATUS sme_configure_modulated_dtim(tHalHandle hal, uint8_t session_id,
 				      uint32_t modulated_dtim);
 
+QDF_STATUS sme_override_listen_interval(tHalHandle h_hal, uint8_t session_id,
+		uint32_t override_li);
+
 QDF_STATUS sme_configure_stats_avg_factor(tHalHandle hal, uint8_t session_id,
 					  uint16_t stats_avg_factor);
 

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

@@ -13733,6 +13733,63 @@ QDF_STATUS sme_configure_modulated_dtim(tHalHandle h_hal, uint8_t session_id,
 	return status;
 }
 
+/**
+ * sme_override_listen_interval() - function to override static LI
+ * @h_hal: SME API to override listen interval
+ * @session_id: session ID
+ * @override_li: new LI value passed by user
+ *
+ * This function override (enable/disable) static a.k.a ini based LI
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS sme_override_listen_interval(tHalHandle h_hal, uint8_t session_id,
+					uint32_t override_li)
+{
+	struct scheduler_msg msg = {0};
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	tpAniSirGlobal mac  = PMAC_STRUCT(h_hal);
+	wma_cli_set_cmd_t *iwcmd;
+
+	iwcmd = qdf_mem_malloc(sizeof(*iwcmd));
+	if (!iwcmd) {
+		QDF_TRACE(QDF_MODULE_ID_SME,
+			  QDF_TRACE_LEVEL_FATAL,
+			  "%s: qdf_mem_malloc failed", __func__);
+		return QDF_STATUS_E_NOMEM;
+	}
+
+	status = sme_acquire_global_lock(&mac->sme);
+
+	if (status == QDF_STATUS_SUCCESS) {
+
+		iwcmd->param_value = override_li;
+		iwcmd->param_vdev_id = session_id;
+		iwcmd->param_id = GEN_PARAM_LISTEN_INTERVAL;
+		iwcmd->param_vp_dev = GEN_CMD;
+		msg.type = WMA_CLI_SET_CMD;
+		msg.reserved = 0;
+		msg.bodyptr = (void *)iwcmd;
+
+		if (!QDF_IS_STATUS_SUCCESS(
+			    scheduler_post_msg(QDF_MODULE_ID_WMA, &msg))) {
+			QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
+				  "%s: Can't post GEN_PARAM_LISTEN_INTERVAL",
+				  __func__);
+			qdf_mem_free(iwcmd);
+			status = QDF_STATUS_E_FAILURE;
+		}
+		sme_release_global_lock(&mac->sme);
+	} else {
+		QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR,
+			  "%s: sme_acquire_global_lock error!",
+			  __func__);
+		qdf_mem_free(iwcmd);
+	}
+
+	return status;
+}
+
 /*
  * sme_wifi_start_logger() - Send the start/stop logging command to WMA
  * to either start/stop logging

+ 2 - 0
core/wma/inc/wma.h

@@ -1029,6 +1029,7 @@ typedef struct {
  * @plink_status_req: link status request
  * @psnr_req: snr request
  * @delay_before_vdev_stop: delay
+ * @override_li: dynamically user configured listen interval
  * @tx_streams: number of tx streams can be used by the vdev
  * @rx_streams: number of rx streams can be used by the vdev
  * @chain_mask: chain mask can be used by the vdev
@@ -1101,6 +1102,7 @@ struct wma_txrx_node {
 #endif
 	uint32_t alt_modulated_dtim;
 	bool alt_modulated_dtim_enabled;
+	uint32_t override_li;
 	uint32_t tx_streams;
 	uint32_t rx_streams;
 	uint32_t chain_mask;

+ 2 - 0
core/wma/inc/wma_api.h

@@ -53,6 +53,7 @@ typedef void *WMA_HANDLE;
  * @GEN_PARAM_CAPTURE_TSF: read tsf
  * @GEN_PARAM_RESET_TSF_GPIO: reset tsf gpio
  * @GEN_VDEV_ROAM_SYNCH_DELAY: roam sync delay
+ * @GEN_PARAM_LISTEN_INTERVAL: listen interval
  */
 enum GEN_PARAM {
 	GEN_VDEV_PARAM_AMPDU = 0x1,
@@ -62,6 +63,7 @@ enum GEN_PARAM {
 	GEN_PARAM_CAPTURE_TSF,
 	GEN_PARAM_RESET_TSF_GPIO,
 	GEN_VDEV_ROAM_SYNCH_DELAY,
+	GEN_PARAM_LISTEN_INTERVAL,
 };
 
 /**

+ 67 - 0
core/wma/src/wma_main.c

@@ -946,6 +946,70 @@ static void wma_set_modulated_dtim(tp_wma_handle wma,
 	}
 }
 
+/**
+ * wma_override_listen_interval() - function to override static/ini based LI
+ * @wma: wma handle
+ * @privcmd: structure containing parameters
+ *
+ * This function override static/ini based LI in firmware
+ *
+ * Return: none
+ */
+static void wma_override_listen_interval(tp_wma_handle wma,
+				   wma_cli_set_cmd_t *privcmd)
+{
+	uint8_t vdev_id = privcmd->param_vdev_id;
+	struct wma_txrx_node *iface =
+		&wma->interfaces[vdev_id];
+	u32 old_override_li, new_override_li, listen_interval;
+	struct sAniSirGlobal *mac;
+	QDF_STATUS ret;
+
+	mac = cds_get_context(QDF_MODULE_ID_PE);
+	if (!mac) {
+		WMA_LOGE(FL("Failed to get mac context"));
+		return;
+	}
+
+	old_override_li = iface->override_li;
+	new_override_li = privcmd->param_value;
+	iface->override_li = new_override_li;
+
+	if (new_override_li &&
+	    (new_override_li != old_override_li)) {
+		listen_interval = new_override_li;
+	} else if (!new_override_li &&
+		   (new_override_li != old_override_li)) {
+		/* Configure default LI as we do on resume */
+		if ((wlan_cfg_get_int(mac, WNI_CFG_LISTEN_INTERVAL,
+				      &listen_interval) != eSIR_SUCCESS)) {
+			QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
+				  "Failed to get value for listen interval");
+			listen_interval = POWERSAVE_DEFAULT_LISTEN_INTERVAL;
+		}
+	} else {
+		return;
+	}
+
+	ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
+			WMI_VDEV_PARAM_LISTEN_INTERVAL,
+			listen_interval);
+	if (QDF_IS_STATUS_ERROR(ret)) {
+		/* Even it fails continue Fw will take default LI */
+		WMA_LOGE("Failed to Set Listen Interval vdevId %d",
+			 vdev_id);
+	}
+	WMA_LOGD("%s: Set Listen Interval vdevId %d Listen Intv %d",
+			__func__, vdev_id, listen_interval);
+	ret = wma_vdev_set_param(wma->wmi_handle,
+			privcmd->param_vdev_id,
+			WMI_VDEV_PARAM_DTIM_POLICY,
+			NORMAL_DTIM);
+	if (QDF_IS_STATUS_ERROR(ret))
+		WMA_LOGE("Failed to Set to Normal DTIM policy");
+
+}
+
 
 /**
  * wma_process_cli_set_cmd() - set parameters to fw
@@ -1088,6 +1152,9 @@ static void wma_process_cli_set_cmd(tp_wma_handle wma,
 		case GEN_PARAM_MODULATED_DTIM:
 			wma_set_modulated_dtim(wma, privcmd);
 			break;
+		case GEN_PARAM_LISTEN_INTERVAL:
+			wma_override_listen_interval(wma, privcmd);
+			break;
 		default:
 			WMA_LOGE("Invalid param id 0x%x",
 				 privcmd->param_id);

+ 5 - 5
core/wma/src/wma_power.c

@@ -1906,8 +1906,8 @@ static void wma_set_vdev_suspend_dtim(tp_wma_handle wma, uint8_t vdev_id)
 				 vdev_id);
 		}
 
-		WMA_LOGD("Set Listen Interval vdevId %d Listen Intv %d",
-			 vdev_id, listen_interval);
+		WMA_LOGD("%s: Set Listen Interval vdevId %d Listen Intv %d",
+			 __func__, vdev_id, listen_interval);
 
 		iface->restore_dtim_setting = true;
 	}
@@ -1921,7 +1921,7 @@ static void wma_set_vdev_suspend_dtim(tp_wma_handle wma, uint8_t vdev_id)
  */
 static inline uint8_t wma_is_user_set_li_params(struct wma_txrx_node *iface)
 {
-       return iface->alt_modulated_dtim_enabled ? 1 : 0;
+	return iface->alt_modulated_dtim_enabled || iface->override_li ? 1 : 0;
 }
 
 /**
@@ -2027,8 +2027,8 @@ static void wma_set_vdev_resume_dtim(tp_wma_handle wma, uint8_t vdev_id)
 				 vdev_id);
 		}
 
-		WMA_LOGD("Set Listen Interval vdevId %d Listen Intv %d",
-			 vdev_id, cfg_data_val);
+		WMA_LOGD("%s: Set Listen Interval vdevId %d Listen Intv %d",
+			 __func__, vdev_id, cfg_data_val);
 
 		iface->restore_dtim_setting = false;