diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 74afedc68ce1..2c4a9880fc38 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/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 + * + * + */ +#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)) diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index ad9047e25476..c16a90ac5dde 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/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), }; diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 58b0f461e71a..0b48b6926d98 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/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) { diff --git a/core/mac/src/pe/lim/lim_send_messages.c b/core/mac/src/pe/lim/lim_send_messages.c index 389921f71c9c..e7bcec98fe04 100644 --- a/core/mac/src/pe/lim/lim_send_messages.c +++ b/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; diff --git a/core/sap/inc/sap_api.h b/core/sap/inc/sap_api.h index 8722900e83f7..61d957f3f641 100644 --- a/core/sap/inc/sap_api.h +++ b/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 { diff --git a/core/sap/src/sap_module.c b/core/sap/src/sap_module.c index 13296132fe1e..14deafcff9be 100644 --- a/core/sap/src/sap_module.c +++ b/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; diff --git a/core/wma/inc/wma_if.h b/core/wma/inc/wma_if.h index 284d163528ca..c5f7603fb6b8 100644 --- a/core/wma/inc/wma_if.h +++ b/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, diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index 9692b3588823..c0f1e1dfafee 100644 --- a/core/wma/inc/wma_internal.h +++ b/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 diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c index 6f3621be7e7f..04bdf28236db 100644 --- a/core/wma/src/wma_dev_if.c +++ b/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; +} diff --git a/core/wma/src/wma_mgmt.c b/core/wma/src/wma_mgmt.c index ec3716d8a2cf..7d9b13173ad6 100644 --- a/core/wma/src/wma_mgmt.c +++ b/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) { diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c index bf738eb65bad..2e6d3e4996b3 100644 --- a/core/wma/src/wma_scan_roam.c +++ b/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);