diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index b7475f6f76..9c993e308a 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -511,16 +511,19 @@ void hdd_conf_hostoffload(hdd_adapter_t *pAdapter, bool fenable) hdd_conf_gtk_offload(pAdapter, fenable); - /* Configure ARP/NS offload during cfg80211 suspend/resume only - * if active mode offload is disabled + /* Configure ARP/NS offload during cfg80211 suspend/resume and + * Enable MC address filtering during cfg80211 suspend + * only if active mode offload is disabled */ if (!pHddCtx->config->active_mode_offload) { + hdd_info("configuring unconfigured active mode offloads"); hdd_conf_arp_offload(pAdapter, fenable); + wlan_hdd_set_mc_addr_list(pAdapter, fenable); + if (pHddCtx->config->fhostNSOffload) hdd_conf_ns_offload(pAdapter, fenable); } EXIT(); - EXIT(); return; } #endif @@ -966,6 +969,23 @@ void wlan_hdd_set_mc_addr_list(hdd_adapter_t *pAdapter, uint8_t set) } #endif +/** + * hdd_update_mcastbcast_filter(): cache multi and broadcast filter for suspend + * @hdd_ctx: hdd context + * + * Cache the configured filter to be used in suspend resume. + */ +static void hdd_update_mcastbcast_filter(hdd_context_t *hdd_ctx) +{ + if (false == hdd_ctx->sus_res_mcastbcast_filter_valid) { + hdd_ctx->sus_res_mcastbcast_filter = + hdd_ctx->configuredMcastBcastFilter; + hdd_ctx->sus_res_mcastbcast_filter_valid = true; + hdd_info("configuredMCastBcastFilter saved = %d", + hdd_ctx->configuredMcastBcastFilter); + } +} + /** * hdd_conf_suspend_ind() - Send Suspend notification * @pHddCtx: HDD Global context @@ -975,69 +995,26 @@ void wlan_hdd_set_mc_addr_list(hdd_adapter_t *pAdapter, uint8_t set) * * Return: None. */ -static void hdd_conf_suspend_ind(hdd_context_t *pHddCtx, - hdd_adapter_t *pAdapter, +static void hdd_send_suspend_ind(hdd_context_t *pHddCtx, + uint32_t conn_state_mask, void (*callback)(void *callbackContext, bool suspended), void *callbackContext) { CDF_STATUS cdf_ret_status = CDF_STATUS_E_FAILURE; - tpSirWlanSuspendParam wlanSuspendParam = - cdf_mem_malloc(sizeof(tSirWlanSuspendParam)); - if (false == pHddCtx->sus_res_mcastbcast_filter_valid) { - pHddCtx->sus_res_mcastbcast_filter = - pHddCtx->configuredMcastBcastFilter; - pHddCtx->sus_res_mcastbcast_filter_valid = true; - hddLog(CDF_TRACE_LEVEL_INFO, "offload: hdd_conf_suspend_ind"); - hddLog(CDF_TRACE_LEVEL_INFO, - "configuredMCastBcastFilter saved = %d", - pHddCtx->configuredMcastBcastFilter); + hdd_info("%s: send wlan suspend indication", __func__); - } - - if (NULL == wlanSuspendParam) { - hddLog(CDF_TRACE_LEVEL_FATAL, - "%s: cdf_mem_alloc failed ", __func__); - return; - } - - hddLog(CDF_TRACE_LEVEL_INFO, - "%s: send wlan suspend indication", __func__); - - /* Configure supported OffLoads */ - hdd_conf_hostoffload(pAdapter, true); - wlanSuspendParam->configuredMcstBcstFilterSetting = - pHddCtx->configuredMcastBcastFilter; - - /* Enable MC address filtering during cfg80211 suspend if active mode - * mode offload is disabled in INI - */ - if (!pHddCtx->config->active_mode_offload) { - hdd_info("enable mc address filtering"); - wlan_hdd_set_mc_addr_list(pAdapter, true); - } - - if ((eConnectionState_Associated == - (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) || - (eConnectionState_IbssConnected == - (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)) - wlanSuspendParam->connectedState = true; - else - wlanSuspendParam->connectedState = false; - - wlanSuspendParam->sessionId = pAdapter->sessionId; cdf_ret_status = - sme_configure_suspend_ind(pHddCtx->hHal, wlanSuspendParam, + sme_configure_suspend_ind(pHddCtx->hHal, conn_state_mask, callback, callbackContext); + if (CDF_STATUS_SUCCESS == cdf_ret_status) { pHddCtx->hdd_mcastbcast_filter_set = true; } else { hddLog(CDF_TRACE_LEVEL_ERROR, FL("sme_configure_suspend_ind returned failure %d"), cdf_ret_status); - - cdf_mem_free(wlanSuspendParam); } } @@ -1077,14 +1054,27 @@ static void hdd_conf_resume_ind(hdd_adapter_t *pAdapter) "offload: in hdd_conf_resume_ind, restoring configuredMcastBcastFilter"); hddLog(CDF_TRACE_LEVEL_INFO, "configuredMcastBcastFilter = %d", pHddCtx->configuredMcastBcastFilter); +} - /* Disable MC address filtering during cfg80211 suspend if active mode - * mode offload is disabled in INI - */ - if (!pHddCtx->config->active_mode_offload) { - hdd_info("disable mc address filtering"); - wlan_hdd_set_mc_addr_list(pAdapter, false); - } +/** + * hdd_update_conn_state_mask(): record info needed by wma_suspend_req + * @adapter: adapter to get info from + * @conn_state_mask: mask of connection info + * + * currently only need to send connection info. + */ +static void +hdd_update_conn_state_mask(hdd_adapter_t *adapter, uint32_t *conn_state_mask) +{ + + eConnectionState connState; + hdd_station_ctx_t *sta_ctx; + sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + connState = sta_ctx->conn_info.connState; + + if (connState == eConnectionState_Associated || + connState == eConnectionState_IbssConnected) + *conn_state_mask |= (1 << adapter->sessionId); } /** @@ -1103,9 +1093,9 @@ hdd_suspend_wlan(void (*callback)(void *callbackContext, bool suspended), CDF_STATUS status; hdd_adapter_t *pAdapter = NULL; hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + uint32_t conn_state_mask = 0; - hddLog(CDF_TRACE_LEVEL_INFO, "%s: WLAN being suspended by OS", - __func__); + hdd_info("%s: WLAN being suspended by OS", __func__); pHddCtx = cds_get_context(CDF_MODULE_ID_HDD); if (!pHddCtx) { @@ -1120,6 +1110,8 @@ hdd_suspend_wlan(void (*callback)(void *callbackContext, bool suspended), return; } + hdd_update_mcastbcast_filter(pHddCtx); + status = hdd_get_front_adapter(pHddCtx, &pAdapterNode); while (NULL != pAdapterNode && CDF_STATUS_SUCCESS == status) { pAdapter = pAdapterNode->pAdapter; @@ -1129,20 +1121,19 @@ hdd_suspend_wlan(void (*callback)(void *callbackContext, bool suspended), wlan_hdd_netif_queue_control(pAdapter, WLAN_NETIF_TX_DISABLE, WLAN_CONTROL_PATH); - /* Send suspend notification down to firmware. - * - * N.B.: Keep this suspend indication at the end - * (before processing next adaptor). This indication - * is considered as trigger point to start WOW (if wow - * is enabled). - */ - hdd_conf_suspend_ind(pHddCtx, pAdapter, callback, - callbackContext); + /* Configure supported OffLoads */ + hdd_conf_hostoffload(pAdapter, true); + + hdd_update_conn_state_mask(pAdapter, &conn_state_mask); status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext); + pAdapterNode = pNext; } + hdd_send_suspend_ind(pHddCtx, conn_state_mask, callback, + callbackContext); + pHddCtx->hdd_wlan_suspended = true; return; diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index e69dbf26b9..5de6302bd6 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -2663,12 +2663,6 @@ typedef struct sSirNoAParam { uint8_t psSelection; } tSirNoAParam, *tpSirNoAParam; -typedef struct sSirWlanSuspendParam { - uint8_t configuredMcstBcstFilterSetting; - uint8_t sessionId; - uint8_t connectedState; -} tSirWlanSuspendParam, *tpSirWlanSuspendParam; - typedef struct sSirWlanResumeParam { uint8_t configuredMcstBcstFilterSetting; } tSirWlanResumeParam, *tpSirWlanResumeParam; diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index 9348ff9d80..7cc219d01c 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -461,7 +461,7 @@ CDF_STATUS sme_configure_rxp_filter(tHalHandle hHal, tpSirWlanSetRxpFilters wlanRxpFilterParam); CDF_STATUS sme_ConfigureAppsCpuWakeupState(tHalHandle hHal, bool isAppsAwake); CDF_STATUS sme_configure_suspend_ind(tHalHandle hHal, - tpSirWlanSuspendParam wlanSuspendParam, + uint32_t conn_state_mask, csr_readyToSuspendCallback, void *callbackContext); CDF_STATUS sme_configure_resume_req(tHalHandle hHal, diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 333c314204..b61de77347 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -6448,7 +6448,7 @@ CDF_STATUS sme_configure_rxp_filter(tHalHandle hHal, --------------------------------------------------------------------------- */ CDF_STATUS sme_configure_suspend_ind(tHalHandle hHal, - tpSirWlanSuspendParam wlanSuspendParam, + uint32_t conn_state_mask, csr_readyToSuspendCallback callback, void *callback_context) { @@ -6467,7 +6467,7 @@ CDF_STATUS sme_configure_suspend_ind(tHalHandle hHal, status = sme_acquire_global_lock(&pMac->sme); if (CDF_IS_STATUS_SUCCESS(status)) { /* serialize the req through MC thread */ - cds_message.bodyptr = wlanSuspendParam; + cds_message.bodyval = conn_state_mask; cds_message.type = WMA_WLAN_SUSPEND_IND; cdf_status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index b9ea71fac3..03486b165a 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -736,7 +736,6 @@ struct wma_wow { bool deauth_enable; bool disassoc_enable; bool bmiss_enable; - bool gtk_pdev_enable; bool gtk_err_enable[WMA_MAX_SUPPORTED_BSS]; #ifdef FEATURE_WLAN_LPHB /* currently supports only vdev 0. diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index 9a2cad03ee..8ef008c795 100644 --- a/core/wma/inc/wma_internal.h +++ b/core/wma/inc/wma_internal.h @@ -993,7 +993,8 @@ CDF_STATUS wma_wow_enter(tp_wma_handle wma, tpSirHalWowlEnterParams info); CDF_STATUS wma_wow_exit(tp_wma_handle wma, tpSirHalWowlExitParams info); -CDF_STATUS wma_suspend_req(tp_wma_handle wma, tpSirWlanSuspendParam info); +CDF_STATUS wma_suspend_req(tp_wma_handle wma); +void wma_update_conn_state(tp_wma_handle wma, uint32_t conn_mask); void wma_del_ts_req(tp_wma_handle wma, tDelTsParams *msg); diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 36e7b8da25..07f511af65 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -3901,122 +3901,172 @@ CDF_STATUS wma_wow_exit(tp_wma_handle wma, tpSirHalWowlExitParams info) } /** - * wma_suspend_req() - Handles suspend indication request received from umac. + * wma_update_conn_state(): synchronize wma & hdd * @wma: wma handle - * @info: suspend params + * @conn_state: boolean array to populate + * @len: validation parameter * - * Return: CDF status + * populate interfaces conn_state with true if the interface + * is a connected client and wow will configure a pattern. */ -CDF_STATUS wma_suspend_req(tp_wma_handle wma, tpSirWlanSuspendParam info) +void wma_update_conn_state(tp_wma_handle wma, uint32_t conn_mask) { - struct wma_txrx_node *iface; - bool connected = false, pno_in_progress = false; - uint8_t i; - bool extscan_in_progress = false; - - wma->no_of_suspend_ind++; - - if (info->sessionId > wma->max_bssid) { - WMA_LOGE("Invalid vdev id (%d)", info->sessionId); - cdf_mem_free(info); - return CDF_STATUS_E_INVAL; - } - - iface = &wma->interfaces[info->sessionId]; - if (!iface) { - WMA_LOGD("vdev %d node is not found", info->sessionId); - cdf_mem_free(info); - return CDF_STATUS_SUCCESS; - } - - if (!wma->wow.magic_ptrn_enable && !iface->ptrn_match_enable) { - cdf_mem_free(info); - - if (wma->no_of_suspend_ind == wma_get_vdev_count(wma)) { - WMA_LOGD("Both magic and pattern byte match are disabled"); - wma->no_of_suspend_ind = 0; - goto send_ready_to_suspend; - } - - return CDF_STATUS_SUCCESS; - } - - iface->conn_state = (info->connectedState) ? true : false; - - /* - * Once WOW is enabled in FW, host can't send anymore - * data to fw. umac sends suspend indication on each - * vdev during platform suspend. WMA has to wait until - * suspend indication received on last vdev before - * enabling wow in fw. - */ - if (wma->no_of_suspend_ind < wma_get_vdev_count(wma)) { - cdf_mem_free(info); - return CDF_STATUS_SUCCESS; - } - - wma->no_of_suspend_ind = 0; - wma->wow.gtk_pdev_enable = 0; - /* - * Enable WOW if any one of the condition meets, - * 1) Is any one of vdev in beaconning mode (in AP mode) ? - * 2) Is any one of vdev in connected state (in STA mode) ? - * 3) Is PNO in progress in any one of vdev ? - * 4) Is Extscan in progress in any one of vdev ? - */ + int i; for (i = 0; i < wma->max_bssid; i++) { - if ((wma_is_vdev_in_beaconning_mode(wma, i) - ) && wma->interfaces[i].vdev_up && - WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, - WMI_SERVICE_BEACON_OFFLOAD)) { - WMA_LOGD("vdev %d is in beaconning mode, enabling wow", - i); - goto enable_wow; - } + if (conn_mask & (1 << i)) + wma->interfaces[i].conn_state = true; + else + wma->interfaces[i].conn_state = false; } + + if (wma->wow.magic_ptrn_enable) + return; + for (i = 0; i < wma->max_bssid; i++) { - if (wma->interfaces[i].conn_state) { - connected = true; - break; - } + if (!wma->interfaces[i].ptrn_match_enable) + wma->interfaces[i].conn_state = false; + } +} + +/** + * wma_is_beaconning_vdev_up(): check if a beaconning vdev is up + * @wma: wma handle + * + * Return TRUE if beaconning vdev is up + */ +static inline +bool wma_is_beaconning_vdev_up(tp_wma_handle wma) +{ + int i; + for (i = 0; i < wma->max_bssid; i++) { + if (wma_is_vdev_in_beaconning_mode(wma, i) + && wma->interfaces[i].vdev_up) + return true; + } + return false; +} + +/** + * wma_support_wow_for_beaconing: wow query for beaconning + * @wma: wma handle + * + * Need to configure wow to enable beaconning offload when + * a beaconing vdev is up and beaonning offload is configured. + * + * Return: true if we need to enable wow for beaconning offload + */ +static inline +bool wma_support_wow_for_beaconing(tp_wma_handle wma) +{ + if (WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_BEACON_OFFLOAD)) { + if (wma_is_beaconning_vdev_up(wma)) + return true; + } + return false; +} + #ifdef FEATURE_WLAN_SCAN_PNO - if (wma->interfaces[i].pno_in_progress) { - WMA_LOGD("PNO is in progress, enabling wow"); - pno_in_progress = true; - break; - } -#endif /* FEATURE_WLAN_SCAN_PNO */ -#ifdef FEATURE_WLAN_EXTSCAN - if (wma->interfaces[i].extscan_in_progress) { - WMA_LOGD("Extscan is in progress, enabling wow"); - extscan_in_progress = true; - break; - } +/** + * wma_is_pnoscan_in_progress(): check if a pnoscan is in progress + * @wma: wma handle + * @vdev_id: vdev_id + * + * Return: TRUE/FALSE + */ +static inline +bool wma_is_pnoscan_in_progress(tp_wma_handle wma, int vdev_id) +{ + return wma->interfaces[vdev_id].pno_in_progress; +} +#else +/** + * wma_is_pnoscan_in_progress(): dummy + * + * Return: False since no pnoscan can be in progress + * when feature flag is not defined. + */ +bool wma_is_pnoscan_in_progress(tp_wma_handle wma, int vdev_id) +{ + return FALSE; +} #endif - } - for (i = 0; i < wma->max_bssid; i++) { - wma->wow.gtk_pdev_enable |= wma->wow.gtk_err_enable[i]; - WMA_LOGD("VDEV_ID:%d, gtk_err_enable[%d]:%d, gtk_pdev_enable:%d", i, - i, wma->wow.gtk_err_enable[i], wma->wow.gtk_pdev_enable); + +#ifdef FEATURE_WLAN_EXTSCAN +static inline +/** + * wma_is_extscan_in_progress(): check if an extscan is in progress + * @wma: wma handle + * @vdev_id: vdev_id + * + * Return: TRUE/FALSvE + */ +bool wma_is_extscan_in_progress(tp_wma_handle wma, int vdev_id) +{ + return wma->interfaces[vdev_id].extscan_in_progress; +} +#else +/** + * wma_is_extscan_in_progress(): dummy + * + * Return: False since no extscan can be in progress + * when feature flag is not defined. + */ +bool wma_is_extscan_in_progress(tp_wma_handle wma, int vdev_id) +{ + return false; +} +#endif + +/** + * wma_is_wow_applicable(): should enable wow + * @wma: wma handle + * + * Enable WOW if any one of the condition meets, + * 1) Is any one of vdev in beaconning mode (in AP mode) ? + * 2) Is any one of vdev in connected state (in STA mode) ? + * 3) Is PNO in progress in any one of vdev ? + * 4) Is Extscan in progress in any one of vdev ? + * + * Return: true if wma needs to configure wow. + */ +bool wma_is_wow_applicable(tp_wma_handle wma) +{ + int vdev_id; + if (wma_support_wow_for_beaconing(wma)) { + WMA_LOGD("vdev is in beaconning mode, enabling wow"); + return true; } - if (!connected && !pno_in_progress && !extscan_in_progress) { - WMA_LOGD("All vdev are in disconnected state and pno/extscan is not in progress, skipping wow"); - cdf_mem_free(info); - goto send_ready_to_suspend; + for (vdev_id = 0; vdev_id < wma->max_bssid; vdev_id++) { + if (wma->interfaces[vdev_id].conn_state) { + WMA_LOGD("STA is connected, enabling wow"); + return true; + } else if (wma_is_pnoscan_in_progress(wma, vdev_id)) { + WMA_LOGD("PNO is in progress, enabling wow"); + return true; + } else if (wma_is_extscan_in_progress(wma, vdev_id)) { + WMA_LOGD("EXT is in progress, enabling wow"); + return true; + } } -enable_wow: - WMA_LOGE("WOW Suspend"); + WMA_LOGD("All vdev are in disconnected state and pno/extscan is not in progress, skipping wow"); + return true; +} - /* - * At this point, suspend indication is received on - * last vdev. It's the time to enable wow in fw. - */ #ifdef FEATURE_WLAN_LPHB - /* LPHB cache, if any item was enabled, should be - * applied. - */ +/** + * wma_apply_lphb(): apply cached LPHB settings + * @wma: wma handle + * + * LPHB cache, if any item was enabled, should be + * applied. + */ +static inline +void wma_apply_lphb(tp_wma_handle wma) +{ + int i; WMA_LOGD("%s: checking LPHB cache", __func__); for (i = 0; i < 2; i++) { if (wma->wow.lphb_cache[i].params.lphbEnableReq.enable) { @@ -4026,14 +4076,28 @@ enable_wow: false); } } +} +#else +void wma_apply_lphb(tp_wma_handle wma) {} #endif /* FEATURE_WLAN_LPHB */ - wma->wow.wow_enable = true; - wma->wow.wow_enable_cmd_sent = false; +/** + * wma_suspend_req() - Handles suspend indication request received from umac. + * @wma: wma handle + * @info: suspend params + * + * Return: CDF status + */ +CDF_STATUS wma_suspend_req(tp_wma_handle wma) +{ + if (wma_is_wow_applicable(wma)) { + WMA_LOGE("WOW Suspend"); + wma_apply_lphb(wma); - cdf_mem_free(info); + wma->wow.wow_enable = true; + wma->wow.wow_enable_cmd_sent = false; + } -send_ready_to_suspend: /* Set the Suspend DTIM Parameters */ wma_set_suspend_dtim(wma); wma_send_status_to_suspend_ind(wma, true); diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 718c66dc9b..935db34862 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -4875,8 +4875,8 @@ CDF_STATUS wma_mc_process_msg(void *cds_context, cds_msg_t *msg) wma_wow_exit(wma_handle, (tpSirHalWowlExitParams) msg->bodyptr); break; case WMA_WLAN_SUSPEND_IND: - wma_suspend_req(wma_handle, - (tpSirWlanSuspendParam) msg->bodyptr); + wma_update_conn_state(wma_handle, msg->bodyval); + wma_suspend_req(wma_handle); break; case WMA_8023_MULTICAST_LIST_REQ: wma_process_mcbc_set_filter_req(wma_handle,