diff --git a/umac/regulatory/core/src/reg_build_chan_list.c b/umac/regulatory/core/src/reg_build_chan_list.c index 01d8802966..8a5010e227 100644 --- a/umac/regulatory/core/src/reg_build_chan_list.c +++ b/umac/regulatory/core/src/reg_build_chan_list.c @@ -1659,6 +1659,9 @@ reg_modify_chan_list_for_avoid_chan_ext(struct wlan_regulatory_pdev_priv_obj if (!psoc) return; + if (reg_check_coex_unsafe_nb_user_prefer(psoc)) + return; + psoc_priv_obj = reg_get_psoc_obj(psoc); if (!psoc_priv_obj) return; diff --git a/umac/regulatory/core/src/reg_callbacks.c b/umac/regulatory/core/src/reg_callbacks.c index 62b0a06902..180d8e8169 100644 --- a/umac/regulatory/core/src/reg_callbacks.c +++ b/umac/regulatory/core/src/reg_callbacks.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 @@ -92,6 +93,7 @@ static void reg_call_chan_change_cbks(struct wlan_objmgr_psoc *psoc, qdf_mem_free(cur_chan_list); } +#ifdef FEATURE_WLAN_CH_AVOID_EXT /** * reg_alloc_and_fill_payload() - Alloc and fill payload structure. * @psoc: Pointer to global psoc structure. @@ -110,6 +112,37 @@ static void reg_alloc_and_fill_payload(struct wlan_objmgr_psoc *psoc, return; } + *payload = qdf_mem_malloc(sizeof(**payload)); + if (*payload) { + (*payload)->psoc = psoc; + (*payload)->pdev = pdev; + if (reg_check_coex_unsafe_nb_user_prefer(psoc)) { + (*payload)->ch_avoid_ind = + !!psoc_priv_obj->ch_avoid_ext_ind; + qdf_mem_copy(&(*payload)->avoid_info.freq_list, + &psoc_priv_obj->avoid_freq_ext_list, + sizeof(psoc_priv_obj->avoid_freq_ext_list)); + psoc_priv_obj->ch_avoid_ext_ind = false; + } + qdf_mem_copy(&(*payload)->avoid_info.chan_list, + &psoc_priv_obj->unsafe_chan_list, + sizeof(psoc_priv_obj->unsafe_chan_list)); + } +} +#else +static void reg_alloc_and_fill_payload(struct wlan_objmgr_psoc *psoc, + struct wlan_objmgr_pdev *pdev, + struct reg_sched_payload **payload) +{ + struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; + + psoc_priv_obj = reg_get_psoc_obj(psoc); + if (!psoc_priv_obj) { + reg_err("reg psoc private obj is NULL"); + *payload = NULL; + return; + } + *payload = qdf_mem_malloc(sizeof(**payload)); if (*payload) { (*payload)->psoc = psoc; @@ -118,13 +151,13 @@ static void reg_alloc_and_fill_payload(struct wlan_objmgr_psoc *psoc, qdf_mem_copy(&(*payload)->avoid_info.freq_list, &psoc_priv_obj->avoid_freq_list, sizeof(psoc_priv_obj->avoid_freq_list)); - qdf_mem_copy(&(*payload)->avoid_info.chan_list, - &psoc_priv_obj->unsafe_chan_list, - sizeof(psoc_priv_obj->unsafe_chan_list)); - psoc_priv_obj->ch_avoid_ind = false; } + qdf_mem_copy(&(*payload)->avoid_info.chan_list, + &psoc_priv_obj->unsafe_chan_list, + sizeof(psoc_priv_obj->unsafe_chan_list)); } +#endif /** * reg_chan_change_flush_cbk_sb() - Flush south bound channel change callbacks. diff --git a/umac/regulatory/core/src/reg_lte.c b/umac/regulatory/core/src/reg_lte.c index 2687c314ff..1a88b89747 100644 --- a/umac/regulatory/core/src/reg_lte.c +++ b/umac/regulatory/core/src/reg_lte.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2014-2020 The Linux Foundation. All rights reserved. - * + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 @@ -28,8 +28,8 @@ #include "reg_services_public_struct.h" #include #include -#include "reg_services_common.h" #include "reg_priv_objs.h" +#include "reg_services_common.h" #include "reg_build_chan_list.h" #include "reg_callbacks.h" #include "reg_lte.h" @@ -185,6 +185,12 @@ QDF_STATUS reg_process_ch_avoid_event(struct wlan_objmgr_psoc *psoc, reg_err("reg psoc private obj is NULL"); return QDF_STATUS_E_FAILURE; } + + if (reg_check_coex_unsafe_nb_user_prefer(psoc)) { + reg_err("skipping LTE Coex unsafe channel change"); + return QDF_STATUS_E_FAILURE; + } + if (CH_AVOID_RULE_DO_NOT_RESTART == psoc_priv_obj->restart_beaconing) { reg_debug("skipping all LTE Coex unsafe channel range"); diff --git a/umac/regulatory/core/src/reg_priv_objs.h b/umac/regulatory/core/src/reg_priv_objs.h index d99149955d..edc3cad95a 100644 --- a/umac/regulatory/core/src/reg_priv_objs.h +++ b/umac/regulatory/core/src/reg_priv_objs.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. - * + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 @@ -178,6 +178,7 @@ struct wlan_regulatory_psoc_priv_obj { #ifdef FEATURE_WLAN_CH_AVOID_EXT bool ch_avoid_ext_ind; struct ch_avoid_ind_type avoid_freq_ext_list; + bool coex_unsafe_chan_nb_user_prefer; #endif }; diff --git a/umac/regulatory/core/src/reg_services_common.c b/umac/regulatory/core/src/reg_services_common.c index 65810960fe..28d2523ba5 100644 --- a/umac/regulatory/core/src/reg_services_common.c +++ b/umac/regulatory/core/src/reg_services_common.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. 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 @@ -6070,11 +6070,16 @@ reg_process_ch_avoid_freq_ext(struct wlan_objmgr_psoc *psoc, struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; uint8_t start_channel; uint8_t end_channel; + int32_t txpower; + bool is_valid_txpower; struct ch_avoid_freq_type *range; enum channel_enum ch_loop; enum channel_enum start_ch_idx; enum channel_enum end_ch_idx; struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj; + uint32_t len; + struct unsafe_ch_list *unsafe_ch_list; + bool coex_unsafe_nb_user_prefer; pdev_priv_obj = reg_get_pdev_obj(pdev); @@ -6088,15 +6093,23 @@ reg_process_ch_avoid_freq_ext(struct wlan_objmgr_psoc *psoc, return QDF_STATUS_E_FAILURE; } - if (pdev_priv_obj->avoid_chan_ext_list.chan_cnt > 0) { - uint32_t len; + unsafe_ch_list = &psoc_priv_obj->unsafe_chan_list; + coex_unsafe_nb_user_prefer = + psoc_priv_obj->coex_unsafe_chan_nb_user_prefer; + if (pdev_priv_obj->avoid_chan_ext_list.chan_cnt > 0) { len = sizeof(pdev_priv_obj->avoid_chan_ext_list.chan_freq_list); pdev_priv_obj->avoid_chan_ext_list.chan_cnt = 0; qdf_mem_zero(&pdev_priv_obj->avoid_chan_ext_list.chan_freq_list, len); } + if (unsafe_ch_list->chan_cnt > 0) { + len = sizeof(unsafe_ch_list->chan_freq_list); + unsafe_ch_list->chan_cnt = 0; + qdf_mem_zero(unsafe_ch_list->chan_freq_list, len); + } + for (i = 0; i < psoc_priv_obj->avoid_freq_ext_list.ch_avoid_range_cnt; i++) { if (pdev_priv_obj->avoid_chan_ext_list.chan_cnt >= @@ -6105,15 +6118,23 @@ reg_process_ch_avoid_freq_ext(struct wlan_objmgr_psoc *psoc, break; } + if (unsafe_ch_list->chan_cnt >= NUM_CHANNELS) { + reg_warn("LTE Coex unsafe channel list full"); + break; + } + start_ch_idx = INVALID_CHANNEL; end_ch_idx = INVALID_CHANNEL; range = &psoc_priv_obj->avoid_freq_ext_list.avoid_freq_range[i]; start_channel = reg_freq_to_chan(pdev, range->start_freq); end_channel = reg_freq_to_chan(pdev, range->end_freq); - reg_debug("start: freq %d, ch %d, end: freq %d, ch %d", + txpower = range->txpower; + is_valid_txpower = range->is_valid_txpower; + + reg_debug("start: freq %d, ch %d, end: freq %d, ch %d txpower %d", range->start_freq, start_channel, range->end_freq, - end_channel); + end_channel, txpower); /* do not process frequency bands that are not mapped to * predefined channels @@ -6148,6 +6169,23 @@ reg_process_ch_avoid_freq_ext(struct wlan_objmgr_psoc *psoc, [pdev_priv_obj->avoid_chan_ext_list.chan_cnt++] = REG_CH_TO_FREQ(ch_loop); + if (coex_unsafe_nb_user_prefer) { + if (unsafe_ch_list->chan_cnt >= + NUM_CHANNELS) { + reg_warn("LTECoex unsafe ch list full"); + break; + } + unsafe_ch_list->txpower[ + unsafe_ch_list->chan_cnt] = + txpower; + unsafe_ch_list->is_valid_txpower[ + unsafe_ch_list->chan_cnt] = + is_valid_txpower; + unsafe_ch_list->chan_freq_list[ + unsafe_ch_list->chan_cnt++] = + REG_CH_TO_FREQ(ch_loop); + } + if (pdev_priv_obj->avoid_chan_ext_list.chan_cnt >= NUM_CHANNELS) { reg_debug("avoid freq ext list full"); @@ -6167,6 +6205,14 @@ reg_process_ch_avoid_freq_ext(struct wlan_objmgr_psoc *psoc, range->start_freq = range->start_freq - HALF_20MHZ_BW; range->end_freq = range->end_freq + HALF_20MHZ_BW; } + + for (ch_loop = 0; ch_loop < + unsafe_ch_list->chan_cnt; ch_loop++) { + if (ch_loop >= NUM_CHANNELS) + break; + reg_debug("Unsafe freq %d", + unsafe_ch_list->chan_freq_list[ch_loop]); + } } return QDF_STATUS_SUCCESS; @@ -6242,7 +6288,14 @@ reg_process_ch_avoid_ext_event(struct wlan_objmgr_psoc *psoc, ch_avoid_event->avoid_freq_range[i].start_freq; range->end_freq = ch_avoid_event->avoid_freq_range[i].end_freq; + range->txpower = + ch_avoid_event->avoid_freq_range[i].txpower; + range->is_valid_txpower = + ch_avoid_event->avoid_freq_range[i].is_valid_txpower; } + + psoc_priv_obj->avoid_freq_ext_list.restriction_mask = + ch_avoid_event->restriction_mask; psoc_priv_obj->avoid_freq_ext_list.ch_avoid_range_cnt = ch_avoid_event->ch_avoid_range_cnt; @@ -6264,6 +6317,19 @@ reg_process_ch_avoid_ext_event(struct wlan_objmgr_psoc *psoc, return status; } + +bool reg_check_coex_unsafe_nb_user_prefer(struct wlan_objmgr_psoc *psoc) +{ + struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj; + + psoc_priv_obj = reg_get_psoc_obj(psoc); + if (!psoc_priv_obj) { + reg_err("reg psoc private obj is NULL"); + return false; + } + + return psoc_priv_obj->coex_unsafe_chan_nb_user_prefer; +} #endif #if defined(CONFIG_AFC_SUPPORT) && defined(CONFIG_BAND_6GHZ) diff --git a/umac/regulatory/core/src/reg_services_common.h b/umac/regulatory/core/src/reg_services_common.h index 83d14e5e30..36f30b8bc1 100644 --- a/umac/regulatory/core/src/reg_services_common.h +++ b/umac/regulatory/core/src/reg_services_common.h @@ -1732,6 +1732,15 @@ bool reg_is_upper_6g_edge_ch_disabled(struct wlan_objmgr_psoc *psoc); QDF_STATUS reg_process_ch_avoid_ext_event(struct wlan_objmgr_psoc *psoc, struct ch_avoid_ind_type *ch_avoid_event); +/** + * reg_check_coex_unsafe_nb_user_prefer() - get coex unsafe nb + * user prefer ini + * @psoc: pointer to psoc + * + * Return: bool + */ + +bool reg_check_coex_unsafe_nb_user_prefer(struct wlan_objmgr_psoc *psoc); #else static inline QDF_STATUS reg_process_ch_avoid_ext_event(struct wlan_objmgr_psoc *psoc, @@ -1739,6 +1748,12 @@ reg_process_ch_avoid_ext_event(struct wlan_objmgr_psoc *psoc, { return QDF_STATUS_SUCCESS; } + +static inline +bool reg_check_coex_unsafe_nb_user_prefer(struct wlan_objmgr_psoc *psoc) +{ + return false; +} #endif #if defined(CONFIG_AFC_SUPPORT) && defined(CONFIG_BAND_6GHZ) diff --git a/umac/regulatory/core/src/reg_utils.c b/umac/regulatory/core/src/reg_utils.c index 39d5823564..7dfbb97908 100644 --- a/umac/regulatory/core/src/reg_utils.c +++ b/umac/regulatory/core/src/reg_utils.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. 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 @@ -375,6 +375,26 @@ reg_get_6g_power_type_for_ctry(struct wlan_objmgr_psoc *psoc, } #endif +#ifdef FEATURE_WLAN_CH_AVOID_EXT +static inline +void reg_get_coex_unsafe_chan_nb_user_prefer( + struct wlan_regulatory_psoc_priv_obj + *psoc_priv_obj, + struct reg_config_vars config_vars) +{ + psoc_priv_obj->coex_unsafe_chan_nb_user_prefer = + config_vars.coex_unsafe_chan_nb_user_prefer; +} +#else +static inline +void reg_get_coex_unsafe_chan_nb_user_prefer( + struct wlan_regulatory_psoc_priv_obj + *psoc_priv_obj, + struct reg_config_vars config_vars) +{ +} +#endif + #ifdef CONFIG_CHAN_FREQ_API bool reg_is_passive_or_disable_for_freq(struct wlan_objmgr_pdev *pdev, qdf_freq_t freq) @@ -793,6 +813,7 @@ QDF_STATUS reg_set_config_vars(struct wlan_objmgr_psoc *psoc, config_vars.enable_5dot9_ghz_chan_in_master_mode; psoc_priv_obj->retain_nol_across_regdmn_update = config_vars.retain_nol_across_regdmn_update; + reg_get_coex_unsafe_chan_nb_user_prefer(psoc_priv_obj, config_vars); status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_REGULATORY_SB_ID); if (QDF_IS_STATUS_ERROR(status)) { diff --git a/umac/regulatory/dispatcher/inc/reg_services_public_struct.h b/umac/regulatory/dispatcher/inc/reg_services_public_struct.h index 96662025a7..53180422c1 100644 --- a/umac/regulatory/dispatcher/inc/reg_services_public_struct.h +++ b/umac/regulatory/dispatcher/inc/reg_services_public_struct.h @@ -48,7 +48,7 @@ #define MAX_STA_VDEV_CNT 4 #define INVALID_VDEV_ID 0xFF #define INVALID_CHANNEL_NUM 0x0 -#define CH_AVOID_MAX_RANGE 4 +#define CH_AVOID_MAX_RANGE (NUM_5GHZ_CHANNELS + NUM_24GHZ_CHANNELS) #define REG_ALPHA2_LEN 2 #define MAX_REG_RULES 10 #define MAX_6G_REG_RULES 5 @@ -1391,6 +1391,8 @@ enum restart_beaconing_on_ch_avoid_rule { * @enable_5dot9_ghz_chan_in_master_mode: 5.9 GHz channel support in * master mode * @retain_nol_across_regdmn_update: Retain the NOL list across the regdomain. + * @coex_unsafe_chan_nb_user_prefer: Honor coex unsafe chan cmd from firmware or + * userspace */ struct reg_config_vars { uint32_t enable_11d_support; @@ -1405,6 +1407,9 @@ struct reg_config_vars { bool enable_11d_in_world_mode; bool enable_5dot9_ghz_chan_in_master_mode; bool retain_nol_across_regdmn_update; +#ifdef FEATURE_WLAN_CH_AVOID_EXT + bool coex_unsafe_chan_nb_user_prefer; +#endif }; /** @@ -1534,20 +1539,25 @@ struct cur_regdmn_info { * struct ch_avoid_freq_type * @start_freq: start freq * @end_freq: end freq + * @txpower: txpower */ struct ch_avoid_freq_type { qdf_freq_t start_freq; qdf_freq_t end_freq; + int32_t txpower; + bool is_valid_txpower; }; /** * struct ch_avoid_ind_type * @ch_avoid_range_cnt: count * @avoid_freq_range: avoid freq range array + * @restriction_mask: restriction mask to apply txpower */ struct ch_avoid_ind_type { uint32_t ch_avoid_range_cnt; struct ch_avoid_freq_type avoid_freq_range[CH_AVOID_MAX_RANGE]; + uint8_t restriction_mask; }; /** @@ -1558,6 +1568,8 @@ struct ch_avoid_ind_type { struct unsafe_ch_list { uint16_t chan_cnt; uint16_t chan_freq_list[NUM_CHANNELS]; + int32_t txpower[NUM_CHANNELS]; + bool is_valid_txpower[NUM_CHANNELS]; }; /**