Browse Source

qcacld-3.0: Add a timer to reduce and resume beacon interval

qcacld-2.0 to qcacld-3.0 propagation

Reduce the beacon interval just before the channel switch.
This would help in reducing the downtime on the STA side which
is waiting for beacons from the AP to resume back transmission.

Switch back the beacon_interval to its original value after
the channel switch based on the timeout. This would ensure
there are atleast some beacons sent with increased frequency.

Change-Id: I37db52713d9e2c78abbb97a7cd0274d9da35bfd2
CRs-Fixed: 1094958
lifeng 8 years ago
parent
commit
7c607dd603

+ 25 - 0
core/hdd/inc/wlan_hdd_cfg.h

@@ -13292,6 +13292,30 @@ enum hdd_external_acs_freq_band {
 #define CFG_DFS_BEACON_TX_ENHANCED_MAX     (1)
 #define CFG_DFS_BEACON_TX_ENHANCED_DEFAULT (0)
 
+/*
+ * gReducedBeaconInterval - beacon interval reduced
+ * @Min: 0
+ * @Max: 100
+ * @Default: 0
+ *
+ * This ini is used to reduce beacon interval before channel
+ * switch (when val great than 0, or the feature is disabled).
+ * It would reduce the downtime on the STA side which is
+ * waiting for beacons from the AP to resume back transmission.
+ * Switch back the beacon_interval to its original value after
+ * channel switch based on the timeout.
+ *
+ * Related: none
+ *
+ * Usage: External
+ *
+ * </ini>
+ */
+#define CFG_REDUCED_BEACON_INTERVAL         "gReducedBeaconInterval"
+#define CFG_REDUCED_BEACON_INTERVAL_MIN     (0)
+#define CFG_REDUCED_BEACON_INTERVAL_MAX     (100)
+#define CFG_REDUCED_BEACON_INTERVAL_DEFAULT (0)
+
 /*
  * Type declarations
  */
@@ -14157,6 +14181,7 @@ struct hdd_config {
 	uint8_t packet_filters_bitmap;
 	uint8_t enable_phy_reg_retention;
 	uint8_t dfs_beacon_tx_enhanced;
+	uint16_t reduced_beacon_interval;
 };
 
 #define VAR_OFFSET(_Struct, _Var) (offsetof(_Struct, _Var))

+ 7 - 0
core/hdd/src/wlan_hdd_cfg.c

@@ -5222,6 +5222,13 @@ struct reg_table_entry g_registry_table[] = {
 		CFG_DFS_BEACON_TX_ENHANCED_DEFAULT,
 		CFG_DFS_BEACON_TX_ENHANCED_MIN,
 		CFG_DFS_BEACON_TX_ENHANCED_MAX),
+
+	REG_VARIABLE(CFG_REDUCED_BEACON_INTERVAL, WLAN_PARAM_Integer,
+		struct hdd_config, reduced_beacon_interval,
+		VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+		CFG_REDUCED_BEACON_INTERVAL_DEFAULT,
+		CFG_REDUCED_BEACON_INTERVAL_MIN,
+		CFG_REDUCED_BEACON_INTERVAL_MAX),
 };
 
 

+ 2 - 0
core/hdd/src/wlan_hdd_hostapd.c

@@ -7598,6 +7598,8 @@ int wlan_hdd_cfg80211_start_bss(struct hdd_adapter *adapter,
 	pConfig->enOverLapCh = iniConfig->gEnableOverLapCh;
 	pConfig->dtim_period = pBeacon->dtim_period;
 	pConfig->dfs_beacon_tx_enhanced = iniConfig->dfs_beacon_tx_enhanced;
+	pConfig->reduced_beacon_interval =
+			iniConfig->reduced_beacon_interval;
 	hdd_debug("acs_mode %d", pConfig->acs_cfg.acs_mode);
 
 	if (pConfig->acs_cfg.acs_mode == true) {

+ 2 - 0
core/mac/src/pe/lim/lim_send_messages.c

@@ -266,6 +266,8 @@ tSirRetStatus lim_send_switch_chnl_params(tpAniSirGlobal pMac,
 	pChnlParams->restart_on_chan_switch = is_restart;
 	pChnlParams->cac_duration_ms = cac_duration_ms;
 	pChnlParams->dfs_regdomain = dfs_regdomain;
+	pChnlParams->reduced_beacon_interval =
+		pMac->sap.SapDfsInfo.reduced_beacon_interval;
 
 	if (cds_is_5_mhz_enabled())
 		pChnlParams->ch_width = CH_WIDTH_5MHZ;

+ 2 - 0
core/sap/inc/sap_api.h

@@ -629,6 +629,7 @@ typedef struct sap_Config {
 	uint8_t sap_chanswitch_mode;
 	bool chan_switch_hostapd_rate_enabled;
 	bool dfs_beacon_tx_enhanced;
+	uint16_t reduced_beacon_interval;
 } tsap_Config_t;
 
 #ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
@@ -723,6 +724,7 @@ typedef struct sSapDfsInfo {
 	uint8_t sap_ch_switch_beacon_cnt;
 	uint8_t sap_ch_switch_mode;
 	bool dfs_beacon_tx_enhanced;
+	uint16_t reduced_beacon_interval;
 } tSapDfsInfo;
 
 typedef struct tagSapCtxList {

+ 2 - 0
core/sap/src/sap_module.c

@@ -748,6 +748,8 @@ QDF_STATUS wlansap_start_bss(struct sap_context *sap_ctx,
 		sap_ctx->sessionId;
 	pmac->sap.SapDfsInfo.dfs_beacon_tx_enhanced =
 		pConfig->dfs_beacon_tx_enhanced;
+	pmac->sap.SapDfsInfo.reduced_beacon_interval =
+				pConfig->reduced_beacon_interval;
 
 	/* Copy MAC filtering settings to sap context */
 	sap_ctx->eSapMacAddrAclMode = pConfig->SapMacaddr_acl;

+ 1 - 0
core/wma/inc/wma_if.h

@@ -938,6 +938,7 @@ typedef struct {
 #endif
 	uint32_t cac_duration_ms;
 	uint32_t dfs_regdomain;
+	uint16_t reduced_beacon_interval;
 } tSwitchChannelParams, *tpSwitchChannelParams;
 
 typedef void (*tpSetLinkStateCallback)(tpAniSirGlobal pMac, void *msgParam,

+ 31 - 0
core/wma/inc/wma_internal.h

@@ -1368,4 +1368,35 @@ int wma_wlan_bt_activity_evt_handler(void *handle, uint8_t *event,
 int wma_peer_ant_info_evt_handler(void *handle, u_int8_t *event,
 	u_int32_t len);
 
+/**
+ * wma_update_beacon_interval() - update beacon interval in fw
+ * @wma: wma handle
+ * @vdev_id: vdev id
+ * @beaconInterval: becon interval
+ *
+ * Return: none
+ */
+void
+wma_update_beacon_interval(tp_wma_handle wma, uint8_t vdev_id,
+				uint16_t beaconInterval);
+
+#define RESET_BEACON_INTERVAL_TIMEOUT 200
+
+struct wma_beacon_interval_reset_req {
+	qdf_timer_t event_timeout;
+	uint8_t vdev_id;
+	uint16_t interval;
+};
+
+/**
+ * wma_fill_beacon_interval_reset_req() - req to reset beacon interval
+ * @wma: wma handle
+ * @vdev_id: vdev id
+ * @beacon_interval: beacon interval
+ * @timeout: timeout val
+ *
+ * Return: status
+ */
+int wma_fill_beacon_interval_reset_req(tp_wma_handle wma, uint8_t vdev_id,
+				uint16_t beacon_interval, uint32_t timeout);
 #endif

+ 54 - 0
core/wma/src/wma_dev_if.c

@@ -5276,3 +5276,57 @@ void wma_store_pdev(void *wma_ctx, struct wlan_objmgr_pdev *pdev)
 	wma->pdev = pdev;
 }
 
+/**
+ * wma_vdev_reset_beacon_interval_timer() - reset beacon interval back
+ * to its original value after the channel switch.
+ *
+ * @data: data
+ *
+ * Return: void
+ */
+static void wma_vdev_reset_beacon_interval_timer(void *data)
+{
+	tp_wma_handle wma;
+	struct wma_beacon_interval_reset_req *req =
+		(struct wma_beacon_interval_reset_req *)data;
+	uint16_t beacon_interval = req->interval;
+	uint8_t vdev_id = req->vdev_id;
+
+	wma = (tp_wma_handle)cds_get_context(QDF_MODULE_ID_WMA);
+	if (NULL == wma) {
+		WMA_LOGE("%s: Failed to get wma", __func__);
+		goto end;
+	}
+
+	/* Change the beacon interval back to its original value */
+	WMA_LOGE("%s: Change beacon interval back to %d",
+			__func__, beacon_interval);
+	wma_update_beacon_interval(wma, vdev_id, beacon_interval);
+
+end:
+	qdf_timer_stop(&req->event_timeout);
+	qdf_timer_free(&req->event_timeout);
+	qdf_mem_free(req);
+}
+
+int wma_fill_beacon_interval_reset_req(tp_wma_handle wma, uint8_t vdev_id,
+				uint16_t beacon_interval, uint32_t timeout)
+{
+	struct wma_beacon_interval_reset_req *req;
+
+	req = qdf_mem_malloc(sizeof(*req));
+	if (!req) {
+		WMA_LOGE("%s: Failed to allocate memory for beacon_interval_reset_req vdev %d",
+			__func__, vdev_id);
+		return -ENOMEM;
+	}
+
+	WMA_LOGD("%s: vdev_id %d ", __func__, vdev_id);
+	req->vdev_id = vdev_id;
+	req->interval = beacon_interval;
+	qdf_timer_init(NULL, &req->event_timeout,
+		wma_vdev_reset_beacon_interval_timer, req, QDF_TIMER_TYPE_SW);
+	qdf_timer_start(&req->event_timeout, timeout);
+
+	return 0;
+}

+ 1 - 9
core/wma/src/wma_mgmt.c

@@ -1423,15 +1423,7 @@ void wma_update_protection_mode(tp_wma_handle wma, uint8_t vdev_id,
 		WMA_LOGD("Updated protection mode %d to target", prot_mode);
 }
 
-/**
- * wma_update_beacon_interval() - update beacon interval in fw
- * @wma: wma handle
- * @vdev_id: vdev id
- * @beaconInterval: becon interval
- *
- * Return: none
- */
-static void
+void
 wma_update_beacon_interval(tp_wma_handle wma, uint8_t vdev_id,
 			   uint16_t beaconInterval)
 {

+ 28 - 0
core/wma/src/wma_scan_roam.c

@@ -3133,6 +3133,7 @@ void wma_set_channel(tp_wma_handle wma, tpSwitchChannelParams params)
 	struct wma_txrx_node *intr = wma->interfaces;
 	struct policy_mgr_hw_mode_params hw_mode = {0};
 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
+	uint16_t beacon_interval_ori;
 
 	WMA_LOGD("%s: Enter", __func__);
 	if (!wma_find_vdev_by_addr(wma, params->selfStaMacAddr, &vdev_id)) {
@@ -3203,6 +3204,33 @@ void wma_set_channel(tp_wma_handle wma, tpSwitchChannelParams params)
 		wma_remove_beacon_filter(wma,
 				&wma->interfaces[req.vdev_id].beacon_filter);
 
+	if ((wma_is_vdev_in_ap_mode(wma, req.vdev_id) == true) &&
+		(params->reduced_beacon_interval)) {
+		/* Reduce the beacon interval just before the channel switch.
+		 * This would help in reducing the downtime on the STA side
+		 * (which is waiting for beacons from the AP to resume back
+		 * transmission). Switch back the beacon_interval to its
+		 * original value after the channel switch based on the
+		 * timeout. This would ensure there are atleast some beacons
+		 * sent with increased frequency.
+		 */
+
+		WMA_LOGD("%s: Changing beacon interval to %d",
+			__func__, params->reduced_beacon_interval);
+
+		/* Add a timer to reset the beacon interval back*/
+		beacon_interval_ori = req.beacon_intval;
+		req.beacon_intval = params->reduced_beacon_interval;
+		if (wma_fill_beacon_interval_reset_req(wma,
+			req.vdev_id,
+			beacon_interval_ori,
+			RESET_BEACON_INTERVAL_TIMEOUT)) {
+
+			WMA_LOGD("%s: Failed to fill beacon interval reset req",
+				__func__);
+		}
+	}
+
 	if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam() &&
 	    wma_is_vdev_up(vdev_id)) {
 		status = wma_switch_channel(wma, &req);