From 3bbf6cb77c0b7d3bec1b863323f2dd8e5534ca8a Mon Sep 17 00:00:00 2001 From: Abhishek Singh Date: Thu, 28 Mar 2019 14:05:43 +0530 Subject: [PATCH] qcacld-3.0: Fix wait timeout for existing channel change request In case of STA+SAP, if STA connect to new channel, driver check if SAP channel switch is required. Before this it wait if channel switch is already in progress, if not it continue and check if channel change is required. While waiting in case where event was set and channel switch was not in progress, the even gets reset after waiting. So if event is not set again, i.e in case SAP channel change is not required. Any subsequent wait on the event will result in timeout. Also while changing channel this event is reset and then the concurrency checks are made and if checks fails the channel change may not happen leaving event in reset state. So wait for event only if channel switch is already in progress. Also reset the event once all concurrency checks have passed and channel change is started. Change-Id: Iffcd8b2bf9dc7cbbd7d939983601cc395ef4c515 CRs-Fixed: 2425145 --- .../policy_mgr/inc/wlan_policy_mgr_api.h | 3 ++ .../policy_mgr/src/wlan_policy_mgr_action.c | 38 ++++++++++++------- .../src/wlan_policy_mgr_init_deinit.c | 4 +- core/hdd/src/wlan_hdd_hostapd.c | 15 +------- core/hdd/src/wlan_hdd_main.c | 29 ++++++++++++++ core/sap/src/sap_module.c | 4 ++ 6 files changed, 65 insertions(+), 28 deletions(-) diff --git a/components/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h b/components/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h index 4c76ef86a2f6..a2a5d6e34b59 100644 --- a/components/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h +++ b/components/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h @@ -1159,6 +1159,8 @@ struct policy_mgr_sme_cbacks { * @hdd_wapi_security_sta_exist: Get whether wapi encription station existing * or not. Some hw doesn't support WAPI encryption concurrency with other * encryption type. + * @hdd_is_chan_switch_in_progress: Check if in any adater channel switch is in + * progress */ struct policy_mgr_hdd_cbacks { void (*sap_restart_chan_switch_cb)(struct wlan_objmgr_psoc *psoc, @@ -1174,6 +1176,7 @@ struct policy_mgr_hdd_cbacks { uint8_t vdev_id); enum QDF_OPMODE (*hdd_get_device_mode)(uint32_t session_id); bool (*hdd_wapi_security_sta_exist)(void); + bool (*hdd_is_chan_switch_in_progress)(void); }; diff --git a/components/cmn_services/policy_mgr/src/wlan_policy_mgr_action.c b/components/cmn_services/policy_mgr/src/wlan_policy_mgr_action.c index 5f9563596454..533112faace8 100644 --- a/components/cmn_services/policy_mgr/src/wlan_policy_mgr_action.c +++ b/components/cmn_services/policy_mgr/src/wlan_policy_mgr_action.c @@ -1409,14 +1409,16 @@ static void __policy_mgr_check_sta_ap_concurrent_ch_intf(void *data) goto end; } - policy_mgr_debug("wait if channel switch is already in progress"); - status = qdf_wait_single_event( - &pm_ctx->channel_switch_complete_evt, - CHANNEL_SWITCH_COMPLETE_TIMEOUT); - - if (!QDF_IS_STATUS_SUCCESS(status)) { - policy_mgr_err("wait for event failed, still continue with channel switch"); + if (pm_ctx->hdd_cbacks.hdd_is_chan_switch_in_progress && + pm_ctx->hdd_cbacks.hdd_is_chan_switch_in_progress()) { + policy_mgr_debug("wait as channel switch is already in progress"); + status = qdf_wait_single_event( + &pm_ctx->channel_switch_complete_evt, + CHANNEL_SWITCH_COMPLETE_TIMEOUT); + if (QDF_IS_STATUS_ERROR(status)) + policy_mgr_err("wait for event failed, still continue with channel switch"); } + if (!pm_ctx->hdd_cbacks.wlan_hdd_get_channel_for_sap_restart) { policy_mgr_err("SAP restart get channel callback in NULL"); goto end; @@ -1433,8 +1435,7 @@ static void __policy_mgr_check_sta_ap_concurrent_ch_intf(void *data) break; } } - if (status != QDF_STATUS_SUCCESS) - policy_mgr_err("Failed to switch SAP channel"); + end: if (work_info) { qdf_mem_free(work_info); @@ -1777,16 +1778,27 @@ QDF_STATUS policy_mgr_set_chan_switch_complete_evt( struct wlan_objmgr_psoc *psoc) { QDF_STATUS status; - struct policy_mgr_psoc_priv_obj *policy_mgr_context; + struct policy_mgr_psoc_priv_obj *pm_ctx; - policy_mgr_context = policy_mgr_get_context(psoc); + pm_ctx = policy_mgr_get_context(psoc); - if (!policy_mgr_context) { + if (!pm_ctx) { policy_mgr_err("Invalid context"); return QDF_STATUS_E_FAILURE; } + + /* + * Set channel_switch_complete_evt only if no vdev has channel switch + * in progress. + */ + if (pm_ctx->hdd_cbacks.hdd_is_chan_switch_in_progress && + pm_ctx->hdd_cbacks.hdd_is_chan_switch_in_progress()) { + policy_mgr_info("Not all channel switch completed"); + return QDF_STATUS_SUCCESS; + } + status = qdf_event_set( - &policy_mgr_context->channel_switch_complete_evt); + &pm_ctx->channel_switch_complete_evt); if (!QDF_IS_STATUS_SUCCESS(status)) { policy_mgr_err("set event failed"); diff --git a/components/cmn_services/policy_mgr/src/wlan_policy_mgr_init_deinit.c b/components/cmn_services/policy_mgr/src/wlan_policy_mgr_init_deinit.c index 3b99c7ce6620..d7757dcc4bee 100644 --- a/components/cmn_services/policy_mgr/src/wlan_policy_mgr_init_deinit.c +++ b/components/cmn_services/policy_mgr/src/wlan_policy_mgr_init_deinit.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -610,6 +610,8 @@ QDF_STATUS policy_mgr_register_hdd_cb(struct wlan_objmgr_psoc *psoc, hdd_cbacks->hdd_get_device_mode; pm_ctx->hdd_cbacks.hdd_wapi_security_sta_exist = hdd_cbacks->hdd_wapi_security_sta_exist; + pm_ctx->hdd_cbacks.hdd_is_chan_switch_in_progress = + hdd_cbacks->hdd_is_chan_switch_in_progress; return QDF_STATUS_SUCCESS; } diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 58a4adcfd773..5cfc263e66b0 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -1816,13 +1816,6 @@ QDF_STATUS hdd_hostapd_sap_event_cb(struct sap_event *sap_event, sap_event->sapevt.sapStartBssCompleteEvent.status; qdf_atomic_set(&adapter->ch_switch_in_progress, 0); - - status = policy_mgr_set_chan_switch_complete_evt( - hdd_ctx->psoc); - if (!QDF_IS_STATUS_SUCCESS(status)) { - hdd_err("set event failed"); - goto stopbss; - } wlansap_get_dfs_ignore_cac(mac_handle, &ignoreCAC); /* DFS requirement: DO NOT transmit during CAC. */ @@ -2620,6 +2613,7 @@ QDF_STATUS hdd_hostapd_sap_event_cb(struct sap_event *sap_event, * is completed */ qdf_atomic_set(&adapter->ch_switch_in_progress, 0); + policy_mgr_set_chan_switch_complete_evt(hdd_ctx->psoc); wlan_hdd_enable_roaming(adapter); return QDF_STATUS_SUCCESS; @@ -2945,13 +2939,6 @@ int hdd_softap_set_channel_change(struct net_device *dev, int target_channel, return -EINVAL; } - status = policy_mgr_reset_chan_switch_complete_evt(hdd_ctx->psoc); - if (!QDF_IS_STATUS_SUCCESS(status)) { - hdd_err("clear event failed"); - qdf_atomic_set(&adapter->ch_switch_in_progress, 0); - return -EINVAL; - } - status = ucfg_policy_mgr_get_sta_sap_scc_lte_coex_chnl(hdd_ctx->psoc, &scc_on_lte_coex); diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 340c29ff0f98..2972d06da0fe 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -2635,6 +2635,32 @@ static enum policy_mgr_con_mode wlan_hdd_get_mode_for_non_connected_vdev( adapter->device_mode); } +/** + * hdd_is_chan_switch_in_progress() - Check if any adapter has channel switch in + * progress + * + * Return: true, if any adapter has channel switch in + * progress else false + */ +static bool hdd_is_chan_switch_in_progress(void) +{ + struct hdd_adapter *adapter = NULL; + struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); + + hdd_for_each_adapter(hdd_ctx, adapter) { + if ((adapter->device_mode == QDF_SAP_MODE || + adapter->device_mode == QDF_P2P_GO_MODE) && + qdf_atomic_read(&adapter->ch_switch_in_progress)) { + hdd_debug("channel switch progress for vdev_id %d", + adapter->vdev_id); + return true; + } + } + + return false; +} + + static void hdd_register_policy_manager_callback( struct wlan_objmgr_psoc *psoc) { @@ -2650,6 +2676,9 @@ static void hdd_register_policy_manager_callback( hdd_cbacks.hdd_get_device_mode = hdd_get_device_mode; hdd_cbacks.hdd_wapi_security_sta_exist = hdd_wapi_security_sta_exist; + hdd_cbacks.hdd_is_chan_switch_in_progress = + hdd_is_chan_switch_in_progress; + if (QDF_STATUS_SUCCESS != policy_mgr_register_hdd_cb(psoc, &hdd_cbacks)) { hdd_err("HDD callback registration with policy manager failed"); diff --git a/core/sap/src/sap_module.c b/core/sap/src/sap_module.c index b508d957cc94..ec67fbebc128 100644 --- a/core/sap/src/sap_module.c +++ b/core/sap/src/sap_module.c @@ -1391,6 +1391,10 @@ QDF_STATUS wlansap_set_channel_change_with_csa(struct sap_context *sap_ctx, return status; } + status = policy_mgr_reset_chan_switch_complete_evt( + mac->psoc); + if (QDF_IS_STATUS_ERROR(status)) + return status; /* * Copy the requested target channel * to sap context.