qcacmn: Fix incorrect 6g supported channels reported for opclass 133 & 134

API reg_get_channels_from_opclassmap populates channels from opclass map to
reg_ap_cap as supported and non-supported channels. But for 6g opclass 133
and 134, non-supported channels were also getting reported as supported
channels.

This was due to an error in the logic of reg_get_channels_from_opclassmap
API for opclass 133 and 134. The 20Mhz channels towards the end of the
channel list in the op_class_tbl were causing the issue.

To address this issue, add a logic to get the supported and non-supported
channels from the cfi list object of op_class_tbl for 6GHz in the
reg_get_channels_from_opclassmap API. Also remove the 40MHz centre channel
calculation condition for 6GHz in reg_get_chan_or_chan_center API as it is
being handled in the new API.

CRs-Fixed: 3133022
Change-Id: If6ea18f79786c8549a1c75c557adffa178dd5c71
This commit is contained in:
Amith Ajith
2022-03-09 06:34:28 +05:30
committed by Madan Koyyalamudi
vanhempi 055dfbe881
commit c3bb3fb37a
3 muutettua tiedostoa jossa 257 lisäystä ja 29 poistoa

Näytä tiedosto

@@ -1474,12 +1474,6 @@ static uint8_t reg_get_chan_or_chan_center(const struct
idx,
NUM_20_MHZ_CHAN_IN_160_MHZ_CHAN,
&center_chan);
} else if ((op_class_tbl->op_class == BW_40_MHZ) &&
(op_class_tbl->op_class == OPCLS_132)) {
reg_get_channel_cen(op_class_tbl,
idx,
NUM_20_MHZ_CHAN_IN_40_MHZ_CHAN,
&center_chan);
} else {
center_chan = op_class_tbl->channels[*idx];
*idx = *idx + 1;
@@ -1488,6 +1482,200 @@ static uint8_t reg_get_chan_or_chan_center(const struct
return center_chan;
}
static inline qdf_freq_t reg_get_nearest_primary_freq(uint16_t bw,
qdf_freq_t cfi_freq,
uint8_t op_class)
{
qdf_freq_t pri_freq;
if (bw <= BW_40_MHZ && op_class != OPCLS_132) {
pri_freq = cfi_freq;
} else {
if (cfi_freq >= BW_10_MHZ)
pri_freq = cfi_freq - BW_10_MHZ;
else
pri_freq = 0;
}
return pri_freq;
}
#ifdef WLAN_FEATURE_11BE
/**
* reg_is_chan_supported()- Check if given channel is supported based on its
* freq provided
* @pdev: Pointer to pdev
* @pri_freq: Primary frequency of the input channel
* @cfi_freq: cfi frequency of the input channel
* @ch_width: Input channel width
*
* Return: True if the channel is supported, else false
*/
static bool reg_is_chan_supported(struct wlan_objmgr_pdev *pdev,
qdf_freq_t pri_freq,
qdf_freq_t cfi_freq,
enum phy_ch_width ch_width)
{
struct reg_channel_list chan_list;
qdf_freq_t center_320;
struct ch_params ch_params;
center_320 = (ch_width == CH_WIDTH_320MHZ) ? cfi_freq : 0;
reg_fill_channel_list(pdev,
pri_freq,
0,
ch_width,
center_320,
&chan_list);
ch_params = chan_list.chan_param[0];
if (ch_params.ch_width == ch_width)
return true;
return false;
}
#else
static bool reg_is_chan_supported(struct wlan_objmgr_pdev *pdev,
qdf_freq_t pri_freq,
qdf_freq_t cfi_freq,
enum phy_ch_width ch_width)
{
struct ch_params ch_params;
ch_params.ch_width = ch_width;
reg_set_channel_params_for_freq(pdev, pri_freq, 0, &ch_params);
if (ch_params.ch_width == ch_width)
return true;
return false;
}
#endif
/**
* reg_is_cfi_supported()- Check if given cfi is supported
* @pdev: Pointer to pdev
* @cfi_freq: cfi frequency
* @bw: bandwidth
*
* Return: True if the cfi is supported, else false
*/
static bool reg_is_cfi_supported(struct wlan_objmgr_pdev *pdev,
qdf_freq_t cfi_freq,
uint16_t bw,
uint8_t op_class)
{
enum phy_ch_width ch_width;
qdf_freq_t pri_freq;
bool is_cfi_supported;
ch_width = reg_find_chwidth_from_bw(bw);
pri_freq = reg_get_nearest_primary_freq(bw, cfi_freq, op_class);
is_cfi_supported = reg_is_chan_supported(pdev,
pri_freq,
cfi_freq,
ch_width);
return is_cfi_supported;
}
/**
* reg_get_cfis_from_opclassmap_for_6g()- Get channels from the opclass map
* for 6GHz
* @pdev: Pointer to pdev
* @cap: Pointer to regdmn_ap_cap_opclass_t
* @op_class_tbl: Pointer to op_class_tbl
*
* Populate channels from opclass map to regdmn_ap_cap_opclass_t as supported
* and non-supported channels for 6Ghz.
*
* Return: void.
*/
static void reg_get_cfis_from_opclassmap_for_6g(
struct wlan_objmgr_pdev *pdev,
struct regdmn_ap_cap_opclass_t *cap,
const struct reg_dmn_op_class_map_t *op_class_tbl)
{
uint8_t n_sup_chans = 0, n_unsup_chans = 0, j;
const struct c_freq_lst *p_cfi_lst = op_class_tbl->p_cfi_lst_obj;
qdf_freq_t cfi_freq;
qdf_freq_t start_freq = op_class_tbl->start_freq;
uint16_t bw = op_class_tbl->chan_spacing;
for (j = 0; j < p_cfi_lst->num_cfis; j++) {
uint8_t cfi = p_cfi_lst->p_cfis_arr[j];
bool is_cfi_supported;
cfi_freq = start_freq + FREQ_TO_CHAN_SCALE * cfi;
is_cfi_supported = reg_is_cfi_supported(pdev,
cfi_freq,
bw,
op_class_tbl->op_class);
if (is_cfi_supported) {
cap->sup_chan_list[n_sup_chans++] = cfi;
cap->num_supported_chan++;
} else {
cap->non_sup_chan_list[n_unsup_chans++] = cfi;
cap->num_non_supported_chan++;
}
}
}
static uint16_t reg_find_nearest_ieee_bw(uint16_t spacing)
{
#define SMALLEST_BW 20
return (spacing / SMALLEST_BW) * SMALLEST_BW;
}
/**
* reg_get_cfis_from_opclassmap_for_non6g()- Get channels from the opclass map
* for non-6GHz
* @pdev: Pointer to pdev
* @cap: Pointer to regdmn_ap_cap_opclass_t
* @op_class_tbl: Pointer to op_class_tbl
*
* Populate channels from opclass map to regdmn_ap_cap_opclass_t as supported
* and non-supported channels for non-6Ghz.
*
* Return: void.
*/
static void reg_get_cfis_from_opclassmap_for_non6g(
struct wlan_objmgr_pdev *pdev,
struct regdmn_ap_cap_opclass_t *cap,
const struct reg_dmn_op_class_map_t *op_class_tbl)
{
qdf_freq_t start_freq = op_class_tbl->start_freq;
uint8_t chan_idx = 0, n_sup_chans = 0, n_unsup_chans = 0;
while (op_class_tbl->channels[chan_idx]) {
uint8_t op_cls_chan;
qdf_freq_t pri_freq;
enum phy_ch_width ch_width;
bool is_supported;
uint16_t opcls_bw;
op_cls_chan = reg_get_chan_or_chan_center(op_class_tbl,
&chan_idx);
pri_freq = start_freq + FREQ_TO_CHAN_SCALE * op_cls_chan;
opcls_bw = reg_find_nearest_ieee_bw(op_class_tbl->chan_spacing);
ch_width = reg_find_chwidth_from_bw(opcls_bw);
pri_freq = reg_get_nearest_primary_freq(opcls_bw,
pri_freq,
op_class_tbl->op_class);
is_supported = reg_is_chan_supported(pdev,
pri_freq,
0,
ch_width);
if (!is_supported) {
cap->non_sup_chan_list[n_unsup_chans++] = op_cls_chan;
cap->num_non_supported_chan++;
} else {
cap->sup_chan_list[n_sup_chans++] = op_cls_chan;
cap->num_supported_chan++;
}
}
}
/**
* reg_get_channels_from_opclassmap()- Get channels from the opclass map
* @pdev: Pointer to pdev
@@ -1509,32 +1697,19 @@ reg_get_channels_from_opclassmap(
const struct reg_dmn_op_class_map_t *op_class_tbl,
bool *is_opclass_operable)
{
uint8_t op_cls_chan;
qdf_freq_t search_freq;
bool is_freq_present;
uint8_t chan_idx = 0, n_sup_chans = 0, n_unsup_chans = 0;
struct regdmn_ap_cap_opclass_t *cap = &reg_ap_cap[index];
while (op_class_tbl->channels[chan_idx]) {
op_cls_chan = op_class_tbl->channels[chan_idx];
search_freq = op_class_tbl->start_freq +
(FREQ_TO_CHAN_SCALE * op_cls_chan);
is_freq_present =
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++] =
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++] =
reg_get_chan_or_chan_center(op_class_tbl,
&chan_idx);
reg_ap_cap[index].num_supported_chan++;
}
if (reg_is_6ghz_op_class(pdev, op_class_tbl->op_class)) {
reg_get_cfis_from_opclassmap_for_6g(pdev,
cap,
op_class_tbl);
} else {
reg_get_cfis_from_opclassmap_for_non6g(pdev,
cap,
op_class_tbl);
}
if (reg_ap_cap[index].num_supported_chan >= 1)
if (cap->num_supported_chan >= 1)
*is_opclass_operable = true;
}

Näytä tiedosto

@@ -8118,3 +8118,46 @@ bool reg_is_freq_idx_enabled(struct wlan_objmgr_pdev *pdev,
}
}
#ifdef WLAN_FEATURE_11BE
enum phy_ch_width reg_find_chwidth_from_bw(uint16_t bw)
{
switch (bw) {
case BW_5_MHZ:
return CH_WIDTH_5MHZ;
case BW_10_MHZ:
return CH_WIDTH_10MHZ;
case BW_20_MHZ:
return CH_WIDTH_20MHZ;
case BW_40_MHZ:
return CH_WIDTH_40MHZ;
case BW_80_MHZ:
return CH_WIDTH_80MHZ;
case BW_160_MHZ:
return CH_WIDTH_160MHZ;
case BW_320_MHZ:
return CH_WIDTH_320MHZ;
default:
return CH_WIDTH_INVALID;
}
}
#else
enum phy_ch_width reg_find_chwidth_from_bw(uint16_t bw)
{
switch (bw) {
case BW_5_MHZ:
return CH_WIDTH_5MHZ;
case BW_10_MHZ:
return CH_WIDTH_10MHZ;
case BW_20_MHZ:
return CH_WIDTH_20MHZ;
case BW_40_MHZ:
return CH_WIDTH_40MHZ;
case BW_80_MHZ:
return CH_WIDTH_80MHZ;
case BW_160_MHZ:
return CH_WIDTH_160MHZ;
default:
return CH_WIDTH_INVALID;
}
}
#endif

Näytä tiedosto

@@ -2217,4 +2217,14 @@ reg_get_best_6g_pwr_type(struct wlan_objmgr_pdev *pdev, qdf_freq_t freq);
*/
enum supported_6g_pwr_types
reg_conv_6g_ap_type_to_supported_6g_pwr_types(enum reg_6g_ap_type ap_pwr_type);
/**
* reg_find_chwidth_from_bw () - Gets channel width for given
* bandwidth
* @bw: Bandwidth
*
* Return: phy_ch_width
*/
enum phy_ch_width reg_find_chwidth_from_bw(uint16_t bw);
#endif