diff --git a/umac/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h b/umac/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h index bbcb7e4c295f..6bd3f0bf1910 100644 --- a/umac/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h +++ b/umac/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h @@ -304,6 +304,7 @@ QDF_STATUS policy_mgr_get_pcl(struct wlan_objmgr_psoc *psoc, /** * policy_mgr_update_with_safe_channel_list() - provides the safe * channel list + * @psoc: PSOC object information * @pcl_channels: channel list * @len: length of the list * @weight_list: Weights of the PCL @@ -314,8 +315,9 @@ QDF_STATUS policy_mgr_get_pcl(struct wlan_objmgr_psoc *psoc, * * Return: None */ -void policy_mgr_update_with_safe_channel_list(uint8_t *pcl_channels, - uint32_t *len, uint8_t *weight_list, uint32_t weight_len); +void policy_mgr_update_with_safe_channel_list(struct wlan_objmgr_psoc *psoc, + uint8_t *pcl_channels, uint32_t *len, + uint8_t *weight_list, uint32_t weight_len); /** * policy_mgr_get_nondfs_preferred_channel() - to get non-dfs preferred channel diff --git a/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_core.c b/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_core.c index 4cc43d08d608..be108750f5c4 100644 --- a/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_core.c +++ b/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_core.c @@ -2106,7 +2106,7 @@ QDF_STATUS policy_mgr_get_channel_list(struct wlan_objmgr_psoc *psoc, *len, i); /* check the channel avoidance list */ - policy_mgr_update_with_safe_channel_list(pcl_channels, len, + policy_mgr_update_with_safe_channel_list(psoc, pcl_channels, len, pcl_weights, weight_len); return status; diff --git a/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_i.h b/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_i.h index 662dfed033b5..d27b3e71add1 100644 --- a/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_i.h +++ b/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_i.h @@ -224,6 +224,8 @@ extern enum policy_mgr_conc_next_action * change is in progress * @enable_mcc_adaptive_scheduler: Enable MCC adaptive scheduler * value from INI + * @unsafe_channel_list: LTE coex channel avoidance list + * @unsafe_channel_count: LTE coex channel avoidance list count */ struct policy_mgr_psoc_priv_obj { struct wlan_objmgr_psoc *psoc; @@ -250,6 +252,8 @@ struct policy_mgr_psoc_priv_obj { struct dual_mac_config dual_mac_cfg; uint32_t hw_mode_change_in_progress; struct policy_mgr_user_cfg user_cfg; + uint16_t unsafe_channel_list[QDF_MAX_NUM_CHAN]; + uint16_t unsafe_channel_count; }; /** @@ -403,4 +407,23 @@ QDF_STATUS policy_mgr_reset_sap_mandatory_channels( bool policy_mgr_get_mode_specific_conn_info(struct wlan_objmgr_psoc *psoc, uint8_t *channel, uint8_t *vdev_id, enum policy_mgr_con_mode mode); + +/** + * policy_mgr_reg_chan_change_callback() - Callback to be + * invoked by regulatory module when valid channel list changes + * @psoc: PSOC object information + * @pdev: PDEV object information + * @chan_list: New channel list + * @avoid_freq_ind: LTE coex avoid channel list + * @arg: Information passed at registration + * + * Get updated channel list from regulatory module + * + * Return: None + */ +void policy_mgr_reg_chan_change_callback(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev, + struct regulatory_channel *chan_list, + struct avoid_freq_ind_data *avoid_freq_ind, + void *arg); #endif diff --git a/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_init_deinit.c b/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_init_deinit.c index 43f325412fdd..fd91357a3ecc 100644 --- a/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_init_deinit.c +++ b/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_init_deinit.c @@ -101,6 +101,9 @@ static QDF_STATUS policy_mgr_pdev_obj_create_cb(struct wlan_objmgr_pdev *pdev, policy_mgr_ctx->pdev = pdev; + wlan_reg_register_chan_change_callback(psoc, + policy_mgr_reg_chan_change_callback, NULL); + return QDF_STATUS_SUCCESS; } @@ -118,6 +121,8 @@ static QDF_STATUS policy_mgr_pdev_obj_destroy_cb(struct wlan_objmgr_pdev *pdev, } policy_mgr_ctx->pdev = NULL; + wlan_reg_unregister_chan_change_callback(psoc, + policy_mgr_reg_chan_change_callback); return QDF_STATUS_SUCCESS; } diff --git a/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_pcl.c b/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_pcl.c index 9ac167e088d6..9b88c76d384b 100644 --- a/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_pcl.c +++ b/umac/cmn_services/policy_mgr/src/wlan_policy_mgr_pcl.c @@ -142,9 +142,95 @@ void policy_mgr_decr_session_set_pcl(struct wlan_objmgr_psoc *psoc, return; } -void policy_mgr_update_with_safe_channel_list(uint8_t *pcl_channels, - uint32_t *len, uint8_t *weight_list, uint32_t weight_len) +void policy_mgr_reg_chan_change_callback(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev, + struct regulatory_channel *chan_list, + struct avoid_freq_ind_data *avoid_freq_ind, + void *arg) { + struct policy_mgr_psoc_priv_obj *pm_ctx; + + pm_ctx = policy_mgr_get_context(psoc); + if (!pm_ctx) { + policy_mgr_err("Invalid Context"); + return; + } + + if (!avoid_freq_ind) { + policy_mgr_debug("avoid_freq_ind NULL"); + return; + } + + pm_ctx->unsafe_channel_count = avoid_freq_ind->chan_list.ch_cnt >= + QDF_MAX_NUM_CHAN ? + QDF_MAX_NUM_CHAN : avoid_freq_ind->chan_list.ch_cnt; + if (pm_ctx->unsafe_channel_count) + qdf_mem_copy(pm_ctx->unsafe_channel_list, + avoid_freq_ind->chan_list.ch_list, + pm_ctx->unsafe_channel_count); + policy_mgr_debug("Channel list update, recieved %d avoided channels", + pm_ctx->unsafe_channel_count); +} + +void policy_mgr_update_with_safe_channel_list(struct wlan_objmgr_psoc *psoc, + uint8_t *pcl_channels, uint32_t *len, + uint8_t *weight_list, uint32_t weight_len) +{ + uint8_t current_channel_list[QDF_MAX_NUM_CHAN]; + uint8_t org_weight_list[QDF_MAX_NUM_CHAN]; + uint8_t is_unsafe = 1; + uint8_t i, j; + uint32_t safe_channel_count = 0, current_channel_count = 0; + struct policy_mgr_psoc_priv_obj *pm_ctx; + + pm_ctx = policy_mgr_get_context(psoc); + if (!pm_ctx) { + policy_mgr_err("Invalid Context"); + return; + } + + if (len) { + current_channel_count = QDF_MIN(*len, QDF_MAX_NUM_CHAN); + } else { + policy_mgr_err("invalid number of channel length"); + return; + } + + if (pm_ctx->unsafe_channel_count == 0) { + policy_mgr_debug("There are no unsafe channels"); + return; + } + + qdf_mem_copy(current_channel_list, pcl_channels, + current_channel_count); + qdf_mem_zero(pcl_channels, current_channel_count); + + qdf_mem_copy(org_weight_list, weight_list, QDF_MAX_NUM_CHAN); + qdf_mem_zero(weight_list, weight_len); + + for (i = 0; i < current_channel_count; i++) { + is_unsafe = 0; + for (j = 0; j < pm_ctx->unsafe_channel_count; j++) { + if (current_channel_list[i] == + pm_ctx->unsafe_channel_list[j]) { + /* Found unsafe channel, update it */ + is_unsafe = 1; + policy_mgr_warn("CH %d is not safe", + current_channel_list[i]); + break; + } + } + if (!is_unsafe) { + pcl_channels[safe_channel_count] = + current_channel_list[i]; + if (safe_channel_count < weight_len) + weight_list[safe_channel_count] = + org_weight_list[i]; + safe_channel_count++; + } + } + *len = safe_channel_count; + return; }