qcacmn: DFS random channel selection for 11BE

Enable the wmi_service to fetch the radar found cfreq from
wmi_service_radar_found_chan_freq_eq_center_freq.

Add changes in DFS random channel selection algorithm
(1) To find a channel of input width 320MHZ. Since 320MHZ in 5G
is 240MHZ (320 - 80 punctured), there are 12 valid 20MHZ subchannels
possible in 240MHZ. Validate the continuity of 240MHZ channel before
declaring the channel to be found.
(2) To find a fallback channel for the input channel
width of CH_WIDTH_320MHZ. The fallback channel of 320MHHZ is
160MHZ.

CRs-Fixed: 3149475
Change-Id: I03cac7f090de20efd912402b5e4df543b47aafed
This commit is contained in:
Priyadarshnee Srinivasan
2022-03-03 13:59:50 +05:30
committed by Madan Koyyalamudi
vanhempi 61178a761e
commit 4f3cbf6b28
3 muutettua tiedostoa jossa 116 lisäystä ja 42 poistoa

Näytä tiedosto

@@ -1,5 +1,6 @@
/*
* Copyright (c) 2012-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
@@ -41,11 +42,12 @@
/* 10MHz channel width */
#define DFS_CH_WIDTH_10MHZ 6
#define DFS_CH_WIDTH_320MHZ 7
/* Invalid channel width */
#define DFS_CH_WIDTH_INVALID 7
#define DFS_CH_WIDTH_INVALID 8
/* Max channel width */
#define DFS_CH_WIDTH_MAX 8
#define DFS_CH_WIDTH_MAX 9
/* Next 5GHz channel number */
#define DFS_80_NUM_SUB_CHANNEL 4
@@ -60,8 +62,9 @@
#define DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET 20
/* Number of 20MHz channels in bitmap */
#define DFS_MAX_20M_SUB_CH 8
#define DFS_MAX_NUM_160_SUBCHAN 8
#define DFS_MAX_NUM_240_SUBCHAN 12
/* Frequency difference between 80+80 MHz */
#define DFS_80P80M_FREQ_DIFF 40

Näytä tiedosto

@@ -957,10 +957,11 @@ dfs_populate_40mhz_available_channel_for_freq(struct wlan_dfs *dfs,
static uint8_t
dfs_populate_available_channel_for_freq(struct wlan_dfs *dfs,
struct chan_bonding_bitmap *bitmap,
uint8_t chan_width,
uint16_t chan_width,
uint16_t *freq_list)
{
switch (chan_width) {
case DFS_CH_WIDTH_320MHZ:
case DFS_CH_WIDTH_160MHZ:
case DFS_CH_WIDTH_80P80MHZ:
case DFS_CH_WIDTH_80MHZ:
@@ -1087,6 +1088,63 @@ static inline void dfs_assign_6g_channels(struct chan_bonding_bitmap *ch_map)
}
#endif
/**
* dfs_find_num_sub_channels_for_chwidth_320_160() - Find the max number
* of sub channels for the given channel width (320/160)
* @chan_width: Channel width
*
* Return - Number of sub-channels
*/
static uint8_t
dfs_find_num_sub_channels_for_chwidth_320_160(uint16_t chan_width)
{
if (chan_width == DFS_CH_WIDTH_160MHZ)
return DFS_MAX_NUM_160_SUBCHAN;
else if (chan_width == DFS_CH_WIDTH_320MHZ)
return DFS_MAX_NUM_240_SUBCHAN;
return 0;
}
/**
* dfs_find_next_chan_start_freq_for_320_160() - Find the next 160/320 channel's
* start freq based on the available channel list. Validate the
* continuity of the sub channels of 160/320M BW, if they are contiguous
* declare channel to be found. Return the start_freq of the channel band found.
* @chan_count: Total number of available channels.
* @freq_list: Available list of frequency
* @chan_width: Target channel width
* @chan_found: Bool to indicate if channel is found
*
* Return: Next chan's start freq
*/
static qdf_freq_t
dfs_find_next_chan_start_freq_for_320_160(uint8_t chan_count,
uint16_t *freq_list,
uint16_t chan_width, bool *chan_found)
{
uint8_t i;
uint8_t count = 0;
qdf_freq_t next_chan_start_freq = 0;
uint8_t num_sub_chans =
dfs_find_num_sub_channels_for_chwidth_320_160(chan_width);
for (i = 1; i < chan_count; i++) {
if ((freq_list[i] - freq_list[i - 1]) ==
DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET)
count++;
else
count = 0;
if (count == num_sub_chans - 1) {
*chan_found = true;
next_chan_start_freq = freq_list[i - count];
break;
}
}
return next_chan_start_freq;
}
/**
* dfs_find_ch_with_fallback_for_freq()- find random channel
* @dfs: Pointer to DFS structure.
@@ -1102,7 +1160,7 @@ static inline void dfs_assign_6g_channels(struct chan_bonding_bitmap *ch_map)
*/
#ifdef CONFIG_CHAN_FREQ_API
static uint16_t dfs_find_ch_with_fallback_for_freq(struct wlan_dfs *dfs,
uint8_t *chan_wd,
uint16_t *chan_wd,
qdf_freq_t *center_freq_seg1,
uint16_t *freq_lst,
uint32_t num_chan)
@@ -1110,9 +1168,9 @@ static uint16_t dfs_find_ch_with_fallback_for_freq(struct wlan_dfs *dfs,
bool flag = false;
uint32_t rand_byte = 0;
struct chan_bonding_bitmap ch_map = { { {0} } };
uint8_t count = 0, i, index = 0, final_cnt = 0;
uint8_t i, index = 0, final_cnt = 0;
uint16_t target_channel = 0;
uint16_t primary_seg_start_ch = 0, sec_seg_ch = 0, new_160_start_ch = 0;
uint16_t primary_seg_start_ch = 0, sec_seg_ch = 0, new_start_ch;
uint16_t final_lst[NUM_CHANNELS] = {0};
/* initialize ch_map for all 80 MHz bands: we have 6 80MHz bands */
@@ -1136,9 +1194,10 @@ static uint16_t dfs_find_ch_with_fallback_for_freq(struct wlan_dfs *dfs,
final_cnt = dfs_populate_available_channel_for_freq(dfs, &ch_map,
*chan_wd, final_lst);
/* If no valid ch bonding found, fallback */
/* If no valid 80mhz bonded chan found, fallback */
if (final_cnt == 0) {
if ((*chan_wd == DFS_CH_WIDTH_160MHZ) ||
if ((*chan_wd == DFS_CH_WIDTH_320MHZ) ||
(*chan_wd == DFS_CH_WIDTH_160MHZ) ||
(*chan_wd == DFS_CH_WIDTH_80P80MHZ) ||
(*chan_wd == DFS_CH_WIDTH_80MHZ)) {
dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
@@ -1155,47 +1214,64 @@ static uint16_t dfs_find_ch_with_fallback_for_freq(struct wlan_dfs *dfs,
/* ch count should be > 8 to switch new channel in 160Mhz band */
if (((*chan_wd == DFS_CH_WIDTH_160MHZ) ||
(*chan_wd == DFS_CH_WIDTH_80P80MHZ)) &&
(final_cnt < DFS_MAX_20M_SUB_CH)) {
(final_cnt < DFS_MAX_NUM_160_SUBCHAN)) {
dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
"from [%d] to 80Mhz", *chan_wd);
*chan_wd = DFS_CH_WIDTH_80MHZ;
return 0;
}
if (*chan_wd == DFS_CH_WIDTH_160MHZ) {
/* ch count should be 12 to switch new 320 channel band (240MHZ) */
if (*chan_wd == DFS_CH_WIDTH_320MHZ) {
if (final_cnt < DFS_MAX_NUM_240_SUBCHAN) {
dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
"from [%d] to 160Mhz", *chan_wd);
*chan_wd = DFS_CH_WIDTH_160MHZ;
return 0;
}
}
if (*chan_wd == DFS_CH_WIDTH_320MHZ ||
*chan_wd == DFS_CH_WIDTH_160MHZ) {
/*
* Only 2 blocks for 160Mhz bandwidth i.e 36-64 & 100-128
* and all the channels in these blocks are continuous
* and separated by 4Mhz.
* Only 1 block of 240 channel is
* available from 100 - 140 comprising of 12 sub 20 channels.
* These are continuous and separated by 20MHZ in
* frequency spectrum.
*/
for (i = 1; ((i < final_cnt)); i++) {
if ((final_lst[i] - final_lst[i - 1]) ==
DFS_NEXT_5GHZ_CHANNEL_FREQ_OFFSET)
count++;
else
count = 0;
if (count == DFS_MAX_20M_SUB_CH - 1) {
flag = true;
new_160_start_ch = final_lst[i - count];
break;
}
}
new_start_ch =
dfs_find_next_chan_start_freq_for_320_160(final_cnt,
final_lst,
*chan_wd,
&flag);
} else if (*chan_wd == DFS_CH_WIDTH_80P80MHZ) {
flag = true;
}
if ((flag == false) && (*chan_wd > DFS_CH_WIDTH_80MHZ)) {
dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
"from [%d] to 80Mhz", *chan_wd);
*chan_wd = DFS_CH_WIDTH_80MHZ;
return 0;
if (!flag) {
if (*chan_wd == DFS_CH_WIDTH_320MHZ) {
dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
"from [%d] to 160Mhz", *chan_wd);
*chan_wd = DFS_CH_WIDTH_160MHZ;
return 0;
} else if (*chan_wd == DFS_CH_WIDTH_160MHZ) {
dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
"from [%d] to 80Mhz", *chan_wd);
*chan_wd = DFS_CH_WIDTH_80MHZ;
return 0;
}
}
if (*chan_wd == DFS_CH_WIDTH_160MHZ) {
if (*chan_wd == DFS_CH_WIDTH_320MHZ ||
*chan_wd == DFS_CH_WIDTH_160MHZ) {
get_random_bytes((uint8_t *)&rand_byte, 1);
rand_byte = (rand_byte + qdf_mc_timer_get_system_ticks())
% DFS_MAX_20M_SUB_CH;
target_channel = new_160_start_ch + (rand_byte *
% dfs_find_num_sub_channels_for_chwidth_320_160
(*chan_wd);
target_channel = new_start_ch + (rand_byte *
DFS_80_NUM_SUB_CHANNEL_FREQ);
} else if (*chan_wd == DFS_CH_WIDTH_80P80MHZ) {
get_random_bytes((uint8_t *)&rand_byte, 1);
@@ -1221,7 +1297,7 @@ static uint16_t dfs_find_ch_with_fallback_for_freq(struct wlan_dfs *dfs,
}
}
if (!sec_seg_ch && (final_cnt == DFS_MAX_20M_SUB_CH))
if (!sec_seg_ch && (final_cnt == DFS_MAX_NUM_160_SUBCHAN))
*chan_wd = DFS_CH_WIDTH_160MHZ;
else if (!sec_seg_ch)
*chan_wd = DFS_CH_WIDTH_80MHZ;
@@ -1478,7 +1554,7 @@ uint16_t dfs_prepare_random_channel_for_freq(struct wlan_dfs *dfs,
uint16_t flag_no_weather = 0;
uint16_t *leakage_adjusted_lst;
uint16_t final_lst[NUM_CHANNELS] = {0};
uint8_t *chan_wd = (uint8_t *)&chan_params->ch_width;
uint16_t *chan_wd = (uint16_t *)&chan_params->ch_width;
bool flag_no_spur_leakage_adj_chans = false;
if (!chan_list || !chan_cnt) {
@@ -1488,7 +1564,7 @@ uint16_t dfs_prepare_random_channel_for_freq(struct wlan_dfs *dfs,
return 0;
}
if (*chan_wd < DFS_CH_WIDTH_20MHZ || *chan_wd > DFS_CH_WIDTH_80P80MHZ) {
if (*chan_wd < DFS_CH_WIDTH_20MHZ || *chan_wd > DFS_CH_WIDTH_320MHZ) {
dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN,
"Invalid chan_wd %d", *chan_wd);
return 0;