diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 9ad137ddbba2..db6ec9c88727 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -3470,6 +3470,21 @@ enum dot11p_mode { #define CFG_TGT_GTX_USR_CFG_MAX (32) #define CFG_TGT_GTX_USR_CFG_DEFAULT (32) +/* + * This parameter will avoid updating ap_sta_inactivity from hostapd.conf + * file. If a station does not send anything in ap_max_inactivity seconds, an + * empty data frame is sent to it in order to verify whether it is + * still in range. If this frame is not ACKed, the station will be + * disassociated and then deauthenticated. This feature is used to + * clear station table of old entries when the STAs move out of the + * range. + * Default : Disable + */ +#define CFG_SAP_MAX_INACTIVITY_OVERRIDE_NAME "gSapMaxInactivityOverride" +#define CFG_SAP_MAX_INACTIVITY_OVERRIDE_MIN (0) +#define CFG_SAP_MAX_INACTIVITY_OVERRIDE_MAX (1) +#define CFG_SAP_MAX_INACTIVITY_OVERRIDE_DEFAULT (0) + /* * This parameter determines that which defered method will be use in rx path * If no bits are set then rx path processing will happen in tasklet context. @@ -4245,6 +4260,7 @@ struct hdd_config { uint32_t tx_aggregation_size; uint32_t rx_aggregation_size; bool sta_prefer_80MHz_over_160MHz; + uint8_t sap_max_inactivity_override; }; #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 b92c3c74e6a5..d2173dc45c66 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -4036,6 +4036,12 @@ REG_TABLE_ENTRY g_registry_table[] = { CFG_RX_AGGREGATION_SIZE_DEFAULT, CFG_RX_AGGREGATION_SIZE_MIN, CFG_RX_AGGREGATION_SIZE_MAX), + REG_VARIABLE(CFG_SAP_MAX_INACTIVITY_OVERRIDE_NAME, WLAN_PARAM_Integer, + struct hdd_config, sap_max_inactivity_override, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_SAP_MAX_INACTIVITY_OVERRIDE_DEFAULT, + CFG_SAP_MAX_INACTIVITY_OVERRIDE_MIN, + CFG_SAP_MAX_INACTIVITY_OVERRIDE_MAX) }; /** @@ -5701,6 +5707,9 @@ void hdd_cfg_print(hdd_context_t *pHddCtx) hdd_info("Name = [%s] Value = [%u]", CFG_TGT_GTX_USR_CFG_NAME, pHddCtx->config->tgt_gtx_usr_cfg); + hdd_info("Name = [%s] Value = [%u]", + CFG_SAP_MAX_INACTIVITY_OVERRIDE_NAME, + pHddCtx->config->sap_max_inactivity_override); hdd_ndp_print_ini_config(pHddCtx); hdd_info("Name = [%s] Value = [%s]", CFG_RM_CAPABILITY_NAME, diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index c5e11a27ec3c..58f8109a831c 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -8900,7 +8900,7 @@ int wlan_hdd_cfg80211_init(struct device *dev, #ifdef QCA_HT_2040_COEX wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE; #endif - + wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER; hdd_add_channel_switch_support(&wiphy->flags); EXIT(); diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 8884800e31f3..e35cea0d183c 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -7825,6 +7825,7 @@ static int __wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy, hdd_context_t *pHddCtx; enum hw_mode_bandwidth channel_width; int status; + struct sme_sta_inactivity_timeout *sta_inactivity_timer; uint8_t channel; ENTER(); @@ -7988,6 +7989,20 @@ static int __wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy, ¶ms->beacon, params->ssid, params->ssid_len, params->hidden_ssid, true); + + if (pHddCtx->config->sap_max_inactivity_override) { + sta_inactivity_timer = qdf_mem_malloc( + sizeof(*sta_inactivity_timer)); + if (!sta_inactivity_timer) { + hdd_err("Failed to allocate Memory"); + return QDF_STATUS_E_FAILURE; + } + sta_inactivity_timer->session_id = pAdapter->sessionId; + sta_inactivity_timer->sta_inactivity_timeout = + params->inactivity_timeout; + sme_update_sta_inactivity_timeout(WLAN_HDD_GET_HAL_CTX + (pAdapter), sta_inactivity_timer); + } } EXIT(); diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 696fa094f5ac..adb7ebf055d9 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -6617,4 +6617,15 @@ struct sme_long_retry_limit { uint8_t session_id; uint32_t long_retry_limit; }; + +/** + * struct sme_sta_inactivity_timeout - set sta_inactivity_timeout + * @session_id: session Id. + * @sta_inactivity_timeout: Timeout to disconnect STA after there + * is no activity. + */ +struct sme_sta_inactivity_timeout { + uint8_t session_id; + uint32_t sta_inactivity_timeout; +}; #endif /* __SIR_API_H */ diff --git a/core/mac/src/include/sir_params.h b/core/mac/src/include/sir_params.h index 69767da30d56..738fbd93e0ab 100644 --- a/core/mac/src/include/sir_params.h +++ b/core/mac/src/include/sir_params.h @@ -637,7 +637,6 @@ typedef struct sSirMbMsgP2p { #define SIR_HAL_ENCRYPT_DECRYPT_MSG (SIR_HAL_ITC_MSG_TYPES_BEGIN + 364) #define SIR_HAL_SHORT_RETRY_LIMIT_CNT (SIR_HAL_ITC_MSG_TYPES_BEGIN + 365) #define SIR_HAL_LONG_RETRY_LIMIT_CNT (SIR_HAL_ITC_MSG_TYPES_BEGIN + 366) - #define SIR_HAL_UPDATE_TX_FAIL_CNT_TH (SIR_HAL_ITC_MSG_TYPES_BEGIN + 367) #define SIR_HAL_MSG_TYPES_END (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF) diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index 6ccc4ed17348..216d032ae0b6 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -1333,4 +1333,20 @@ QDF_STATUS sme_update_short_retry_limit_threshold(tHalHandle hal_handle, struct sme_short_retry_limit *short_retry_limit_th); QDF_STATUS sme_update_long_retry_limit_threshold(tHalHandle hal_handle, struct sme_long_retry_limit *long_retry_limit_th); + +/** + * sme_update_sta_inactivity_timeout(): Update sta_inactivity_timeout to FW + * @hal: Handle returned by mac_open + * @sta_inactivity_timer: struct for sta inactivity timer + * + * If a station does not send anything in sta_inactivity_timeout seconds, an + * empty data frame is sent to it in order to verify whether it is + * still in range. If this frame is not ACKed, the station will be + * disassociated and then deauthenticated. + * + * Return: QDF_STATUS_SUCCESS or non-zero on failure. +*/ +QDF_STATUS sme_update_sta_inactivity_timeout(tHalHandle hal_handle, + struct sme_sta_inactivity_timeout *sta_inactivity_timer); + #endif /* #if !defined( __SME_API_H ) */ diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 993f46866e3a..063c52606517 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -12355,6 +12355,45 @@ QDF_STATUS sme_update_long_retry_limit_threshold(tHalHandle hal_handle, return status; } +/** + * sme_update_sta_inactivity_timeout(): Update sta_inactivity_timeout to FW + * @hal: Handle returned by mac_open + * @session_id: Session ID on which sta_inactivity_timeout needs + * to be updated to FW + * @sta_inactivity_timeout: sta inactivity timeout. + * + * If a station does not send anything in sta_inactivity_timeout seconds, an + * empty data frame is sent to it in order to verify whether it is + * still in range. If this frame is not ACKed, the station will be + * disassociated and then deauthenticated. + * + * Return: QDF_STATUS_SUCCESS or non-zero on failure. +*/ +QDF_STATUS sme_update_sta_inactivity_timeout(tHalHandle hal_handle, + struct sme_sta_inactivity_timeout *sta_inactivity_timer) +{ + struct sme_sta_inactivity_timeout *inactivity_time; + void *wma_handle; + + wma_handle = cds_get_context(QDF_MODULE_ID_WMA); + inactivity_time = qdf_mem_malloc(sizeof(*inactivity_time)); + if (NULL == inactivity_time) { + QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, + "%s: fail to alloc inactivity_time", __func__); + return QDF_STATUS_E_FAILURE; + } + QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO, + FL("sta_inactivity_timeout: %d"), + sta_inactivity_timer->sta_inactivity_timeout); + inactivity_time->session_id = sta_inactivity_timer->session_id; + inactivity_time->sta_inactivity_timeout = + sta_inactivity_timer->sta_inactivity_timeout; + + wma_update_sta_inactivity_timeout(wma_handle, + inactivity_time); + return QDF_STATUS_SUCCESS; +} + /** * sme_get_reg_info() - To get registration info * @hHal: HAL context diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index bda463e010c6..ee582700448b 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -183,7 +183,6 @@ #define WMA_IPV6_PROTO_GET_MIN_LEN 21 #define WMA_IPV6_PKT_INFO_GET_MIN_LEN 62 #define WMA_ICMPV6_SUBTYPE_GET_MIN_LEN 55 - /** * ds_mode: distribution system mode * @IEEE80211_NO_DS: NO DS at either side @@ -388,6 +387,7 @@ enum ds_mode { #define WMA_NEXT_20MHZ_START_CH_DIFF 4 #define WMA_DEFAULT_HW_MODE_INDEX 0xFFFF +#define TWO_THIRD (2/3) /** * WMA hardware mode list bit-mask definitions. @@ -2335,3 +2335,5 @@ void wma_register_packetdump_callback( tp_wma_packetdump_cb wma_mgmt_tx_packetdump_cb, tp_wma_packetdump_cb wma_mgmt_rx_packetdump_cb); void wma_deregister_packetdump_callback(void); +void wma_update_sta_inactivity_timeout(tp_wma_handle wma, + struct sme_sta_inactivity_timeout *sta_inactivity_timer); diff --git a/core/wma/inc/wma_types.h b/core/wma/inc/wma_types.h index 4e6309e63172..4818795c3e1f 100644 --- a/core/wma/inc/wma_types.h +++ b/core/wma/inc/wma_types.h @@ -475,7 +475,6 @@ #define WMA_UPDATE_WEP_DEFAULT_KEY SIR_HAL_UPDATE_WEP_DEFAULT_KEY #define WMA_SEND_FREQ_RANGE_CONTROL_IND SIR_HAL_SEND_FREQ_RANGE_CONTROL_IND #define WMA_ENCRYPT_DECRYPT_MSG SIR_HAL_ENCRYPT_DECRYPT_MSG - /* Bit 6 will be used to control BD rate for Management frames */ #define HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME 0x40 diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 8072b06b94ae..b8b06998477d 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -6029,6 +6029,56 @@ static QDF_STATUS wma_update_long_retry_limit(tp_wma_handle wma, return QDF_STATUS_SUCCESS; } +/* + * wma_update_sta_inactivity_timeout() - Set sta_inactivity_timeout to fw + * @wma_handle: WMA handle + * @sta_inactivity_timer: sme_sta_inactivity_timeout + * + * This function is used to set sta_inactivity_timeout. + * If a station does not send anything in sta_inactivity_timeout seconds, an + * empty data frame is sent to it in order to verify whether it is + * still in range. If this frame is not ACKed, the station will be + * disassociated and then deauthenticated. + * + * Return: None + */ +void wma_update_sta_inactivity_timeout(tp_wma_handle wma, + struct sme_sta_inactivity_timeout *sta_inactivity_timer) +{ + uint8_t vdev_id; + uint32_t max_unresponsive_time; + uint32_t min_inactive_time, max_inactive_time; + + if (!wma || !wma->wmi_handle) { + WMA_LOGE("WMA is closed, can not issue sta_inactivity_timeout"); + return; + } + vdev_id = sta_inactivity_timer->session_id; + max_unresponsive_time = sta_inactivity_timer->sta_inactivity_timeout; + max_inactive_time = max_unresponsive_time * TWO_THIRD; + min_inactive_time = max_unresponsive_time - max_inactive_time; + + if (wma_vdev_set_param(wma->wmi_handle, vdev_id, + WMI_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS, + min_inactive_time)) + WMA_LOGE("Failed to Set AP MIN IDLE INACTIVE TIME"); + + if (wma_vdev_set_param(wma->wmi_handle, vdev_id, + WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS, + max_inactive_time)) + WMA_LOGE("Failed to Set AP MAX IDLE INACTIVE TIME"); + + if (wma_vdev_set_param(wma->wmi_handle, vdev_id, + WMI_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS, + max_unresponsive_time)) + WMA_LOGE("Failed to Set MAX UNRESPONSIVE TIME"); + + WMA_LOGI("%s:vdev_id:%d min_inactive_time: %u max_inactive_time: %u max_unresponsive_time: %u", + __func__, vdev_id, + min_inactive_time, max_inactive_time, + max_unresponsive_time); +} + /** * wma_mc_process_msg() - process wma messages and call appropriate function. * @cds_context: cds context