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.