From a6a139298a1b511a5312feb76d21e7db7905ca12 Mon Sep 17 00:00:00 2001 From: Hariharan Basuthkar Date: Mon, 10 Feb 2020 21:44:48 +0530 Subject: [PATCH] qcacmn: Add an API reg_get_center_channel in the Regulatory In a SON WFA testcase, the QCA AP advertises the channel set in operating class 128 as individual IEEE channel number (for eg. 36, 40, 44, 48 etc.) instead of center channel (for eg. 42, 58, 106 etc.) to the third party AP. As a result, the third party AP creates Front Haul VAPs in High Band radio when the QCA AP is configured to Low Band, due to incorrect channel set advertised to it. To fix this issue, add an API reg_get_chan_or_chan_center to calculate the center channel number for a 80MHz, 80_80 MHz and 160 MHz bandwidth channel, and use it to calculate the center channel number within the channel set for a particular operating class in the operating class table. Change-Id: Idf7df70c8d01ed79b43d0ba21db7b07189f3f710 CRs-Fixed: 2612258 --- umac/regulatory/core/src/reg_opclass.c | 75 +++++++++++++++++-- .../regulatory/core/src/reg_services_common.h | 4 +- .../inc/reg_services_public_struct.h | 5 +- 3 files changed, 75 insertions(+), 9 deletions(-) diff --git a/umac/regulatory/core/src/reg_opclass.c b/umac/regulatory/core/src/reg_opclass.c index 79505cea4fff..27d0db4006df 100644 --- a/umac/regulatory/core/src/reg_opclass.c +++ b/umac/regulatory/core/src/reg_opclass.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2020 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 @@ -619,6 +619,68 @@ reg_get_op_class_tbl_by_chan_map(const struct *op_class_tbl = global_op_class; } +/** + * reg_get_channel_cen - Calculate central channel in the channel set. + * + * @op_class_tbl - Pointer to op_class_tbl. + * @idx - Pointer to channel index. + * @num_channels - Number of channels. + * @center_chan - Pointer to center channel number + * + * Return : void + */ +static void reg_get_channel_cen(const struct + reg_dmn_op_class_map_t *op_class_tbl, + uint8_t *idx, + uint8_t num_channels, + uint8_t *center_chan) +{ + uint8_t i; + uint16_t new_chan = 0; + + for (i = *idx; i < (*idx + num_channels); i++) + new_chan += op_class_tbl->channels[i]; + + new_chan = new_chan / num_channels; + *center_chan = new_chan; + *idx = *idx + num_channels; +} + +/** + * reg_get_chan_or_chan_center - Calculate central channel in the channel set. + * + * @op_class_tbl - Pointer to op_class_tbl. + * @idx - Pointer to channel index. + * + * Return : Center channel number + */ +static uint8_t reg_get_chan_or_chan_center(const struct + reg_dmn_op_class_map_t *op_class_tbl, + uint8_t *idx) +{ + uint8_t center_chan; + + if (((op_class_tbl->chan_spacing == BW_80_MHZ) && + (op_class_tbl->behav_limit == BIT(BEHAV_NONE))) || + ((op_class_tbl->chan_spacing == BW_80_MHZ) && + (op_class_tbl->behav_limit == BIT(BEHAV_BW80_PLUS)))) { + reg_get_channel_cen(op_class_tbl, + idx, + NUM_20_MHZ_CHAN_IN_80_MHZ_CHAN, + ¢er_chan); + } else if (op_class_tbl->chan_spacing == BW_160_MHZ) { + reg_get_channel_cen(op_class_tbl, + idx, + NUM_20_MHZ_CHAN_IN_160_MHZ_CHAN, + ¢er_chan); + } else { + center_chan = op_class_tbl->channels[*idx]; + *idx = *idx + 1; + } + + return center_chan; +} + /** * reg_get_channels_from_opclassmap()- Get channels from the opclass map * @pdev: Pointer to pdev @@ -653,17 +715,16 @@ reg_get_channels_from_opclassmap( reg_is_freq_present_in_cur_chan_list(pdev, search_freq); if (!is_freq_present) { - reg_ap_cap[index]. - non_sup_chan_list[n_unsup_chans++] = - op_class_tbl->channels[chan_idx]; + reg_ap_cap[index].non_sup_chan_list[n_unsup_chans++] = + reg_get_chan_or_chan_center(op_class_tbl, + &chan_idx); reg_ap_cap[index].num_non_supported_chan++; } else { reg_ap_cap[index].sup_chan_list[n_sup_chans++] = - op_class_tbl->channels[chan_idx]; + reg_get_chan_or_chan_center(op_class_tbl, + &chan_idx); reg_ap_cap[index].num_supported_chan++; } - - chan_idx++; } if (reg_ap_cap[index].num_supported_chan >= 1) diff --git a/umac/regulatory/core/src/reg_services_common.h b/umac/regulatory/core/src/reg_services_common.h index ffd0091ebeb4..0be9a49d7c44 100644 --- a/umac/regulatory/core/src/reg_services_common.h +++ b/umac/regulatory/core/src/reg_services_common.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -31,6 +31,8 @@ #define FREQ_TO_CHAN_SCALE 5 /* The distance between the 80Mhz center and the nearest 20Mhz channel */ #define NEAREST_20MHZ_CHAN_FREQ_OFFSET 10 +#define NUM_20_MHZ_CHAN_IN_80_MHZ_CHAN 4 +#define NUM_20_MHZ_CHAN_IN_160_MHZ_CHAN 8 #ifdef CONFIG_CHAN_NUM_API #define REG_MIN_24GHZ_CH_NUM channel_map[MIN_24GHZ_CHANNEL].chan_num diff --git a/umac/regulatory/dispatcher/inc/reg_services_public_struct.h b/umac/regulatory/dispatcher/inc/reg_services_public_struct.h index 2400e696f935..7b0077627fea 100644 --- a/umac/regulatory/dispatcher/inc/reg_services_public_struct.h +++ b/umac/regulatory/dispatcher/inc/reg_services_public_struct.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020 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 @@ -61,6 +61,9 @@ #define REGULATORY_PHYMODE_NO11AC BIT(4) #define REGULATORY_PHYMODE_NO11AX BIT(5) +#define BW_80_MHZ 80 +#define BW_160_MHZ 160 + /** * enum dfs_reg - DFS region * @DFS_UNINIT_REGION: un-initialized region