diff --git a/umac/dfs/core/src/dfs_random_chan_sel.h b/umac/dfs/core/src/dfs_random_chan_sel.h index f755d1c1ca..96a525774b 100644 --- a/umac/dfs/core/src/dfs_random_chan_sel.h +++ b/umac/dfs/core/src/dfs_random_chan_sel.h @@ -126,6 +126,29 @@ #define DFS_IS_CHAN_JAPAN_INDOOR_FREQ(_ch)(((_ch) >= 5180) && ((_ch) <= 5320)) #define DFS_IS_CHAN_JAPAN_OUTDOOR_FREQ(_ch)(((_ch) >= 5500) && ((_ch) <= 5720)) #define DFS_IS_CHAN_JAPAN_W53_FREQ(_ch) (((_ch) >= 5260) && ((_ch) <= 5320)) +/* + * Spur or leakage transmissions is observed in Spruce HW in + * frequencies from 5260MHz to 5320MHz when one of the following + * conditions is true, + * i) The AP is transmitting in 52/56/60/64 in 80MHz mode and then the AP + * moves to the adjacent channel 36/44/48 in 80MHz mode and starts + * transmitting. + * ii) The AP is transmitting in 36/44/48/52/56/60/64 in 160MHz mode and then + * the AP moves to the adjacent channel 36/44/48 in 80MHz mode and starts + * transmitting. + * Hence, center frequencies from 5260MHz to 5320MHz in Spruce HW are called + * Spruce Spur 80MHz Frequencies and, center frequencies from 5180MHz and + * 5320MHz except 5200MHz are called Spruce Spur 160MHz Frequencies. + */ +/* Channels 52/56/60/64 in 80MHz */ +#define DFS_IS_CHAN_SPRUCE_SPUR_FREQ_80MHZ(_ch) \ + (((_ch) >= 5260) && ((_ch) <= 5320)) +/* 36/44/48/52/56/60/64 in 160MHz mode */ +#define DFS_IS_CHAN_SPRUCE_SPUR_FREQ_160MHZ(_ch) \ + (((_ch) >= 5180) && ((_ch) <= 5320) && ((_ch) != 5200)) +/* Avoid channels 36/44/48 */ +#define DFS_IS_SPRUCE_SPUR_AVOID_FREQS(_ch) \ + (((_ch) >= 5180) && ((_ch) <= 5240) && ((_ch) != 5200)) #endif /** diff --git a/umac/dfs/core/src/misc/dfs_random_chan_sel.c b/umac/dfs/core/src/misc/dfs_random_chan_sel.c index c585ef544b..6d4d3b52d6 100644 --- a/umac/dfs/core/src/misc/dfs_random_chan_sel.c +++ b/umac/dfs/core/src/misc/dfs_random_chan_sel.c @@ -1457,6 +1457,7 @@ uint16_t dfs_prepare_random_channel_for_freq(struct wlan_dfs *dfs, uint16_t *leakage_adjusted_lst; uint16_t final_lst[NUM_CHANNELS] = {0}; uint8_t *chan_wd = (uint8_t *)&chan_params->ch_width; + bool flag_no_spur_leakage_adj_chans = false; if (!chan_list || !chan_cnt) { dfs_info(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, @@ -1481,6 +1482,8 @@ uint16_t dfs_prepare_random_channel_for_freq(struct wlan_dfs *dfs, dfs_region, acs_info); flag_no_weather = (dfs_region == DFS_ETSI_REGION) ? flags & DFS_RANDOM_CH_FLAG_NO_WEATHER_CH : 0; + flag_no_spur_leakage_adj_chans = + flags & DFS_RANDOM_CH_FLAG_NO_SPRUCE_SPUR_ADJ_CH; /* list adjusted after leakage has been marked */ leakage_adjusted_lst = qdf_mem_malloc(random_chan_cnt * @@ -1566,6 +1569,29 @@ uint16_t dfs_prepare_random_channel_for_freq(struct wlan_dfs *dfs, continue; } + /* + * Spur or leakage transmissions is observed in Spruce HW in + * frequencies from 5260MHz to 5320MHz when one of the following + * conditions is true, + * i) The AP is transmitting in 52/56/60/64 in 80MHz mode and + * then the AP moves to the adjacent channel 36/44/48 in 80MHz + * mode and starts transmitting. + * ii) The AP is transmitting in 36/44/48/52/56/60/64 in 160MHz + * mode and then the AP moves to the adjacent channel 36/44/48 + * in 80MHz mode and starts transmitting. + * + * The random channel selection algorithm prevents the channel + * movement mentioned above, thereby eliminating the leakage. + */ + if (flag_no_spur_leakage_adj_chans && + DFS_IS_SPRUCE_SPUR_AVOID_FREQS(target_freq) && + *chan_wd == DFS_CH_WIDTH_80MHZ) { + dfs_debug(dfs, WLAN_DEBUG_DFS_RANDOM_CHAN, + "skip spruce spur causing (adjacent) channel=%hu", + target_freq); + continue; + } + if (target_freq) break; } while (true); diff --git a/umac/dfs/dispatcher/inc/wlan_dfs_ioctl.h b/umac/dfs/dispatcher/inc/wlan_dfs_ioctl.h index edeb223809..4cce96483b 100644 --- a/umac/dfs/dispatcher/inc/wlan_dfs_ioctl.h +++ b/umac/dfs/dispatcher/inc/wlan_dfs_ioctl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2011, 2016-2021 The Linux Foundation. All rights reserved. * Copyright (c) 2010, Atheros Communications Inc. * All Rights Reserved. * @@ -214,6 +214,9 @@ struct dfs_bangradar_params { /* Flag to exclude all 6GHz channels */ #define DFS_RANDOM_CH_FLAG_NO_6GHZ_CH 0x00400 /* 0000 0100 0000 0000 */ +/* Flag to exclude spruce spur adjacent channels */ +#define DFS_RANDOM_CH_FLAG_NO_SPRUCE_SPUR_ADJ_CH \ + 0x0800 /* 0000 1000 0000 0000 */ /** * struct wlan_dfs_caps - DFS capability structure. * @wlan_dfs_ext_chan_ok: Can radar be detected on the extension chan? diff --git a/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h b/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h index 71b5fcc499..e5ab2a869d 100644 --- a/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h +++ b/umac/dfs/dispatcher/inc/wlan_dfs_utils_api.h @@ -225,6 +225,34 @@ QDF_STATUS utils_dfs_stacac_stop(struct wlan_objmgr_pdev *pdev); */ QDF_STATUS utils_dfs_get_usenol(struct wlan_objmgr_pdev *pdev, uint16_t *usenol); +/* + * utils_dfs_radar_disable() - Disables the radar. + * @pdev: Pointer to DFS pdev object. + * + * Return: true if Spruce spur WAR is applicable else false. + * + * Spur or leakage transmissions is observed in Spruce HW in + * frequencies from 5260MHz to 5320MHz when one of the following + * conditions is true, + * i) The AP is transmitting in 52/56/60/64 in 80MHz mode and then the AP + * moves to the adjacent channel 36/44/48 in 80MHz mode and starts + * transmitting. + * ii) The AP is transmitting in 36/44/48/52/56/60/64 in 160MHz mode and then + * the AP moves to the adjacent channel 36/44/48 in 80MHz mode and starts + * transmitting. + * + * Hence, the spruce spur WAR becomes applicable when, + * a) the target is Spruce, + * b) the primary channel is 52/56/60/64, and the home channel width is 80MHz. + * c) or, the primary channel is 36/44/48/52/56/60/64 and the home channel width + * is 160MHz. + * + * When the conditions (a) and (b) or (c) is true, random channel selection + * should make sure to prevent moving to the adjacent channels 36/44/48 in + * 80MHz mode. Failing to do so will cause spur transmissions in channel 52 + * through 64. + */ +bool utils_dfs_is_spruce_spur_war_applicable(struct wlan_objmgr_pdev *pdev); /** * utils_dfs_radar_disable() - Disables the radar. diff --git a/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c b/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c index 5a22dbbff2..027700d402 100644 --- a/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c +++ b/umac/dfs/dispatcher/src/wlan_dfs_utils_api.c @@ -319,6 +319,62 @@ QDF_STATUS utils_dfs_get_usenol(struct wlan_objmgr_pdev *pdev, uint16_t *usenol) } qdf_export_symbol(utils_dfs_get_usenol); +bool utils_dfs_is_spruce_spur_war_applicable(struct wlan_objmgr_pdev *pdev) +{ + struct wlan_dfs *dfs; + struct wlan_objmgr_psoc *psoc; + struct wlan_lmac_if_tx_ops *tx_ops; + uint32_t target_type; + struct wlan_lmac_if_target_tx_ops *tgt_tx_ops; + qdf_freq_t cur_freq; + + dfs = wlan_pdev_get_dfs_obj(pdev); + if (!dfs) + return false; + + psoc = dfs->dfs_soc_obj->psoc; + + tx_ops = wlan_psoc_get_lmac_if_txops(psoc); + if (!tx_ops) { + dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "tx_ops is NULL"); + return false; + } + + tgt_tx_ops = &tx_ops->target_tx_ops; + target_type = lmac_get_target_type(dfs->dfs_pdev_obj); + + /* Is the target Spruce? */ + if (!tgt_tx_ops->tgt_is_tgt_type_qcn6122) + return false; + + if (!tgt_tx_ops->tgt_is_tgt_type_qcn6122(target_type)) + return false; + + cur_freq = dfs->dfs_curchan->dfs_ch_freq; + + /* Is the current channel width 80MHz? */ + if (WLAN_IS_CHAN_MODE_80(dfs->dfs_curchan)) { + /* is the primary channel 52/56/60/64? */ + bool is_chan_spur_80mhzfreq = + DFS_IS_CHAN_SPRUCE_SPUR_FREQ_80MHZ(cur_freq); + if (is_chan_spur_80mhzfreq) + return true; + return false; + } + + /* If the current channel width is not 80, is it 160MHz? */ + if (WLAN_IS_CHAN_MODE_160(dfs->dfs_curchan)) { + /* is the primary channel 36/44/48/52/56/60/64? */ + bool is_chan_spur_160mhz_freq = + DFS_IS_CHAN_SPRUCE_SPUR_FREQ_160MHZ(cur_freq); + if (is_chan_spur_160mhz_freq) + return true; + return false; + } + + return false; +} + QDF_STATUS utils_dfs_radar_disable(struct wlan_objmgr_pdev *pdev) { struct wlan_dfs *dfs;