From 79b64ac4badf06445f235f7a1bccb9d941c60371 Mon Sep 17 00:00:00 2001 From: Chaithanya Garrepalli Date: Tue, 7 Jan 2020 17:28:49 +0530 Subject: [PATCH 1/7] qcacmn: fix potential memory leak in dp_rx_process There is a chance of leak of RX buffers if peer disconnects while we are in middle for processing the list of MSDUs in a AMSDU Change-Id: I0081ec96da95ea570903dbd5d91c866c8c141667 --- dp/wifi3.0/dp_rx.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/dp/wifi3.0/dp_rx.c b/dp/wifi3.0/dp_rx.c index 11dfaf6a67..8047f66f1b 100644 --- a/dp/wifi3.0/dp_rx.c +++ b/dp/wifi3.0/dp_rx.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-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 @@ -2237,9 +2237,20 @@ done: dp_peer_unref_del_find_by_id(peer); } - if (deliver_list_head && peer) - dp_rx_deliver_to_stack(vdev, peer, deliver_list_head, - deliver_list_tail); + if (qdf_likely(deliver_list_head)) { + if (qdf_likely(peer)) + dp_rx_deliver_to_stack(vdev, peer, deliver_list_head, + deliver_list_tail); + else { + nbuf = deliver_list_head; + while (nbuf) { + next = nbuf->next; + nbuf->next = NULL; + dp_rx_deliver_to_stack_no_peer(soc, nbuf); + nbuf = next; + } + } + } if (dp_rx_enable_eol_data_check(soc) && rx_bufs_used) { if (quota) { From 86eba5902ec023f25d72a414e37a51aa58647f24 Mon Sep 17 00:00:00 2001 From: Vignesh Mohan Date: Wed, 23 Oct 2019 17:34:14 +0530 Subject: [PATCH 2/7] qcacmn: Reinit DFS after HW mode switch (phase 2) Supported dynamic HW mode switches: DBS (full band 5G and 2G) <-> DBS_SBS (low band 5G, high band 5G and 2G) Description of the changes: 1. NOL conversion: a. Introduce a temporary NOL list copy structure in DFS psoc obj. b. When mode switch is triggered: i. Stop the NOL timers and clear the data, to avoid processing NOL expiry during mode switch. ii. Allocate the psoc NOL copy for the target num_radios. iii. Store the NOL data of each radio to the target pdev ID (pdev ID after mode switch) in the psoc NOL copy, using a unified mux/demux API. c. After mode switch is completed: i. Resume NOL by re-initializing the list from the temporary psoc copy. ii. Free the psoc copy after mode switch is complete. iii. Note: changes are made to support pause and resume of NOL, increasing NOL timeout by a few milliseconds. 2. PreCAC list conversion: a. When mode switch is triggered: i. Stop the existing preCAC timer and send ADFS abort command to FW. b. When mode switch is completed: i. Unify/separate the preCAC list if the target mode is DBS/DBS_SBS respectively, using a single API. ii. Start ADFS again. 3. Radar detection lock: a. While detecting radar, acquire a lock to avoid handling user triggered mode_switch during this process. Release the lock once radar processing is completed and CSA start is triggered. 4. Radar detection/CAC completion defer during mode switch: a. While detecting radar or CAC completion, check if mode switch is in progress. If yes, defer the processing and wait for mode switch to complete before handling the events. b. Note: Precedence is Radar over CAC, i.e., if CAC processing is waiting and radar is received, CAC completion is no longer handled. CRs-Fixed: 2580403 Change-Id: I506f3b569bad2e351c6f336e50f203cf5fa8b223 --- umac/dfs/core/src/dfs.h | 105 +++++++++++++++++- umac/dfs/core/src/dfs_zero_cac.h | 28 ++++- umac/dfs/core/src/misc/dfs.c | 26 ++++- umac/dfs/core/src/misc/dfs_cac.c | 37 +++--- umac/dfs/core/src/misc/dfs_nol.c | 100 ++++++++++++++++- .../src/misc/dfs_process_radar_found_ind.c | 59 ++++++++-- umac/dfs/dispatcher/inc/wlan_dfs_ioctl.h | 4 +- umac/dfs/dispatcher/inc/wlan_dfs_lmac_api.h | 11 +- umac/dfs/dispatcher/inc/wlan_dfs_mlme_api.h | 20 +++- umac/dfs/dispatcher/inc/wlan_dfs_tgt_api.h | 75 ++++++++++++- umac/dfs/dispatcher/inc/wlan_dfs_ucfg_api.h | 10 +- .../dispatcher/src/wlan_dfs_init_deinit_api.c | 6 +- umac/dfs/dispatcher/src/wlan_dfs_lmac_api.c | 19 +++- umac/dfs/dispatcher/src/wlan_dfs_mlme_api.c | 18 ++- umac/dfs/dispatcher/src/wlan_dfs_tgt_api.c | 101 ++++++++++++++++- .../lmac_if/inc/wlan_lmac_if_def.h | 24 ++++ .../lmac_if/src/wlan_lmac_if.c | 15 ++- 17 files changed, 618 insertions(+), 40 deletions(-) diff --git a/umac/dfs/core/src/dfs.h b/umac/dfs/core/src/dfs.h index 1aa1bde92c..24f5a84c95 100644 --- a/umac/dfs/core/src/dfs.h +++ b/umac/dfs/core/src/dfs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2013, 2016-2020 The Linux Foundation. All rights reserved. * Copyright (c) 2005-2006 Atheros Communications, Inc. * * Permission to use, copy, modify, and/or distribute this software for any @@ -197,6 +197,12 @@ #define WLAN_DFS_DATA_STRUCT_LOCK_DESTROY(_dfs) \ qdf_spinlock_destroy(&(_dfs)->dfs_data_struct_lock) +/* Wrappers to call MLME radar during mode switch lock. */ +#define DFS_RADAR_MODE_SWITCH_LOCK(_dfs) \ + dfs_mlme_acquire_radar_mode_switch_lock((_dfs)->dfs_pdev_obj) +#define DFS_RADAR_MODE_SWITCH_UNLOCK(_dfs) \ + dfs_mlme_release_radar_mode_switch_lock((_dfs)->dfs_pdev_obj) + /* Mask for time stamp from descriptor */ #define DFS_TSMASK 0xFFFFFFFF /* Shift for time stamp from descriptor */ @@ -897,6 +903,20 @@ struct dfs_event_log { #define FREQ_OFFSET_BOUNDARY_FOR_80MHZ 40 +/** + * struct dfs_mode_switch_defer_params - Parameters storing DFS information + * before defer, as part of HW mode switch. + * + * @radar_params: Deferred radar parameters. + * @is_cac_completed: Boolean representing CAC completion event. + * @is_radar_detected: Boolean representing radar event. + */ +struct dfs_mode_switch_defer_params { + struct radar_found_info *radar_params; + bool is_cac_completed; + bool is_radar_detected; +}; + /** * struct wlan_dfs - The main dfs structure. * @dfs_debug_mask: Current debug bitmask. @@ -1061,6 +1081,9 @@ struct dfs_event_log { * be blocked and this variable should be * false so that HW pulses and synthetic * pulses do not get mixed up. + * defer timer running. + * @dfs_defer_params: DFS deferred event parameters (allocated + * only for the duration of defer alone). */ struct wlan_dfs { uint32_t dfs_debug_mask; @@ -1224,6 +1247,7 @@ struct wlan_dfs { #if defined(WLAN_DFS_PARTIAL_OFFLOAD) && defined(WLAN_DFS_SYNTHETIC_RADAR) bool dfs_allow_hw_pulses; #endif + struct dfs_mode_switch_defer_params dfs_defer_params; }; #if defined(QCA_SUPPORT_AGILE_DFS) || defined(ATH_SUPPORT_ZERO_CAC_DFS) @@ -1254,6 +1278,7 @@ struct wlan_dfs_priv { * @dfs_precac_timer: agile precac timer * @dfs_precac_timer_running: precac timer running flag * @ocac_status: Off channel CAC complete status + * @dfs_nol_ctx: dfs NOL data for all radios. */ struct dfs_soc_priv_obj { struct wlan_objmgr_psoc *psoc; @@ -1268,6 +1293,7 @@ struct dfs_soc_priv_obj { bool precac_state_started; bool ocac_status; #endif + struct dfsreq_nolinfo *dfs_psoc_nolinfo; }; /** @@ -2725,4 +2751,81 @@ int dfs_reinit_timers(struct wlan_dfs *dfs); * Return: None. */ void dfs_reset_dfs_prevchan(struct wlan_dfs *dfs); + +/** + * dfs_init_tmp_psoc_nol() - Init temporary psoc NOL structure. + * @dfs: Pointer to wlan_dfs object. + * @num_radios: Num of radios in the PSOC. + * + * Return: void. + */ +void dfs_init_tmp_psoc_nol(struct wlan_dfs *dfs, uint8_t num_radios); + +/** + * dfs_deinit_tmp_psoc_nol() - De-init temporary psoc NOL structure. + * @dfs: Pointer to wlan_dfs object. + * + * Return: void. + */ +void dfs_deinit_tmp_psoc_nol(struct wlan_dfs *dfs); + +/** + * dfs_save_dfs_nol_in_psoc() - Save NOL data of given pdev. + * @dfs: Pointer to wlan_dfs object. + * @pdev_id: The pdev ID which will have the NOL data. + * @low_5ghz_freq: The low 5GHz frequency value of the target pdev id. + * @high_5ghz_freq: The high 5GHz frequency value of the target pdev id. + * + * Based on the frequency of the NOL channel, copy it to the target pdev_id + * structure in psoc. + * + * Return: void. + */ +void dfs_save_dfs_nol_in_psoc(struct wlan_dfs *dfs, + uint8_t pdev_id, + uint16_t low_5ghz_freq, + uint16_t high_5ghz_freq); + +/** + * dfs_reinit_nol_from_psoc_copy() - Reinit saved NOL data to corresponding + * DFS object. + * @dfs: Pointer to wlan_dfs object. + * @pdev_id: pdev_id of the given dfs object. + * + * Return: void. + */ +void dfs_reinit_nol_from_psoc_copy(struct wlan_dfs *dfs, uint8_t pdev_id); + +/** + * dfs_is_hw_mode_switch_in_progress() - Check if HW mode switch in progress. + * @dfs: Pointer to wlan_dfs object. + * + * Return: True if mode switch is in progress, else false. + */ +bool dfs_is_hw_mode_switch_in_progress(struct wlan_dfs *dfs); + +/** + * dfs_start_mode_switch_defer_timer() - start mode switch defer timer. + * @dfs: Pointer to wlan_dfs object. + * + * Return: void. + */ +void dfs_start_mode_switch_defer_timer(struct wlan_dfs *dfs); + +/** + * dfs_complete_deferred_tasks() - Process mode switch completion event and + * handle deffered tasks. + * @dfs: Pointer to wlan_dfs object. + * + * Return: void. + */ +void dfs_complete_deferred_tasks(struct wlan_dfs *dfs); + +/** + * dfs_process_cac_completion() - Process DFS CAC completion event. + * @dfs: Pointer to wlan_dfs object. + * + * Return: void. + */ +void dfs_process_cac_completion(struct wlan_dfs *dfs); #endif /* _DFS_H_ */ diff --git a/umac/dfs/core/src/dfs_zero_cac.h b/umac/dfs/core/src/dfs_zero_cac.h index 405916fc8f..dd718e97f4 100644 --- a/umac/dfs/core/src/dfs_zero_cac.h +++ b/umac/dfs/core/src/dfs_zero_cac.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. * Copyright (c) 2007-2008 Sam Leffler, Errno Consulting * All rights reserved. * @@ -823,6 +823,32 @@ dfs_get_precac_chan_state_for_freq(struct wlan_dfs *dfs, */ void dfs_zero_cac_reset(struct wlan_dfs *dfs); +/** + * dfs_reinit_precac_lists() - Reinit DFS preCAC lists. + * @src_dfs: Source DFS from which the preCAC list is copied. + * @dest_dfs: Destination DFS to which the preCAC list is copied. + * @low_5g_freq: Low 5G frequency value of the destination DFS. + * @high_5g_freq: High 5G frequency value of the destination DFS. + * + * Copy all the preCAC list entries from the source DFS to the destination DFS + * which fall within the frequency range of low_5g_freq and high_5g_freq. + * + * Return: None (void). + */ +#if defined(WLAN_DFS_PARTIAL_OFFLOAD) && !defined(QCA_MCL_DFS_SUPPORT) +void dfs_reinit_precac_lists(struct wlan_dfs *src_dfs, + struct wlan_dfs *dest_dfs, + uint16_t low_5g_freq, + uint16_t high_5g_freq); +#else +static inline void dfs_reinit_precac_lists(struct wlan_dfs *src_dfs, + struct wlan_dfs *dest_dfs, + uint16_t low_5g_freq, + uint16_t high_5g_freq) +{ +} +#endif + /** * dfs_is_precac_done_on_ht20_40_80_chan() - Is precac done on a * VHT20/40/80 channel. diff --git a/umac/dfs/core/src/misc/dfs.c b/umac/dfs/core/src/misc/dfs.c index a1abe7ff93..e05d6be2c5 100644 --- a/umac/dfs/core/src/misc/dfs.c +++ b/umac/dfs/core/src/misc/dfs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. * Copyright (c) 2002-2006, Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any @@ -31,6 +31,7 @@ #include "../dfs_full_offload.h" #include #include "wlan_dfs_utils_api.h" +#include "../dfs_process_radar_found_ind.h" #include "../dfs_partial_offload_radar.h" /* Disable NOL in FW. */ @@ -917,3 +918,26 @@ void dfs_reset_dfs_prevchan(struct wlan_dfs *dfs) { qdf_mem_zero(dfs->dfs_prevchan, sizeof(struct dfs_channel)); } + +bool dfs_is_hw_mode_switch_in_progress(struct wlan_dfs *dfs) +{ + return lmac_dfs_is_hw_mode_switch_in_progress(dfs->dfs_pdev_obj); +} + +void dfs_complete_deferred_tasks(struct wlan_dfs *dfs) +{ + if (dfs->dfs_defer_params.is_radar_detected) { + /* Handle radar event that was deferred and free the temporary + * storage of the radar event parameters. + */ + dfs_process_radar_ind(dfs, dfs->dfs_defer_params.radar_params); + qdf_mem_free(dfs->dfs_defer_params.radar_params); + dfs->dfs_defer_params.is_radar_detected = false; + } else if (dfs->dfs_defer_params.is_cac_completed) { + /* Handle CAC completion event that was deferred for HW mode + * switch. + */ + dfs_process_cac_completion(dfs); + dfs->dfs_defer_params.is_cac_completed = false; + } +} diff --git a/umac/dfs/core/src/misc/dfs_cac.c b/umac/dfs/core/src/misc/dfs_cac.c index 7f35ea90ce..0bbeb00858 100644 --- a/umac/dfs/core/src/misc/dfs_cac.c +++ b/umac/dfs/core/src/misc/dfs_cac.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. * Copyright (c) 2007-2008 Sam Leffler, Errno Consulting * All rights reserved. * @@ -122,24 +122,16 @@ static void dfs_clear_cac_started_chan(struct wlan_dfs *dfs) sizeof(dfs->dfs_cac_started_chan)); } -/** - * dfs_cac_timeout() - DFS cactimeout function. - * - * Sets dfs_cac_timer_running to 0 and dfs_cac_valid_timer. - */ -#ifdef CONFIG_CHAN_FREQ_API -static os_timer_func(dfs_cac_timeout) +void dfs_process_cac_completion(struct wlan_dfs *dfs) { - struct wlan_dfs *dfs = NULL; enum phy_ch_width ch_width = CH_WIDTH_INVALID; uint16_t primary_chan_freq = 0, secondary_chan_freq = 0; struct dfs_channel *dfs_curchan; - OS_GET_TIMER_ARG(dfs, struct wlan_dfs *); dfs->dfs_cac_timer_running = 0; dfs_curchan = dfs->dfs_curchan; - dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "cac expired, chan %d curr time %d", + dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, "cac expired, chan %d cur time %d", dfs->dfs_curchan->dfs_ch_freq, (qdf_system_ticks_to_msecs(qdf_system_ticks()) / 1000)); @@ -154,12 +146,13 @@ static os_timer_func(dfs_cac_timeout) dfs_curchan->dfs_ch_mhz_freq_seg2, dfs_curchan->dfs_ch_flags); dfs_debug(dfs, WLAN_DEBUG_DFS, - "CAC timer on channel %u (%u MHz) stopped due to radar", + "CAC timer on chan %u (%u MHz) stopped due to radar", dfs_curchan->dfs_ch_ieee, dfs_curchan->dfs_ch_freq); } else { dfs_debug(dfs, WLAN_DEBUG_DFS, - "CAC timer on channel %u (%u MHz) expired; no radar detected", + "CAC timer on channel %u (%u MHz) expired;" + "no radar detected", dfs_curchan->dfs_ch_ieee, dfs_curchan->dfs_ch_freq); @@ -195,6 +188,24 @@ static os_timer_func(dfs_cac_timeout) dfs->dfs_defer_precac_channel_change = 0; } } + +/** + * dfs_cac_timeout() - DFS cactimeout function. + * + * Sets dfs_cac_timer_running to 0 and dfs_cac_valid_timer. + */ +#ifdef CONFIG_CHAN_FREQ_API +static os_timer_func(dfs_cac_timeout) +{ + struct wlan_dfs *dfs = NULL; + + OS_GET_TIMER_ARG(dfs, struct wlan_dfs *); + + if (dfs_is_hw_mode_switch_in_progress(dfs)) + dfs->dfs_defer_params.is_cac_completed = true; + else + dfs_process_cac_completion(dfs); +} #else #ifdef CONFIG_CHAN_NUM_API static os_timer_func(dfs_cac_timeout) diff --git a/umac/dfs/core/src/misc/dfs_nol.c b/umac/dfs/core/src/misc/dfs_nol.c index 31f096c299..eda749ad4c 100644 --- a/umac/dfs/core/src/misc/dfs_nol.c +++ b/umac/dfs/core/src/misc/dfs_nol.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. * Copyright (c) 2002-2010, Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any @@ -899,3 +899,101 @@ void dfs_remove_spoof_channel_from_nol(struct wlan_dfs *dfs) } #endif #endif + +void dfs_init_tmp_psoc_nol(struct wlan_dfs *dfs, uint8_t num_radios) +{ + struct dfs_soc_priv_obj *dfs_soc_obj = dfs->dfs_soc_obj; + + if (WLAN_UMAC_MAX_PDEVS < num_radios) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, + "num_radios (%u) exceeds limit", num_radios); + return; + } + + /* Allocate the temporary psoc NOL copy structure for the number + * of radios provided. + */ + dfs_soc_obj->dfs_psoc_nolinfo = + qdf_mem_malloc(sizeof(struct dfsreq_nolinfo) * num_radios); +} + +void dfs_deinit_tmp_psoc_nol(struct wlan_dfs *dfs) +{ + struct dfs_soc_priv_obj *dfs_soc_obj = dfs->dfs_soc_obj; + + if (!dfs_soc_obj->dfs_psoc_nolinfo) + return; + + qdf_mem_free(dfs_soc_obj->dfs_psoc_nolinfo); + dfs_soc_obj->dfs_psoc_nolinfo = NULL; +} + +void dfs_save_dfs_nol_in_psoc(struct wlan_dfs *dfs, + uint8_t pdev_id, + uint16_t low_5ghz_freq, + uint16_t high_5ghz_freq) +{ + struct dfs_soc_priv_obj *dfs_soc_obj = dfs->dfs_soc_obj; + struct dfsreq_nolinfo tmp_nolinfo, *nolinfo; + uint32_t i, num_chans = 0; + uint16_t tmp_freq; + + if (!dfs->dfs_nol_count) + return; + + if (!dfs_soc_obj->dfs_psoc_nolinfo) + return; + + nolinfo = &dfs_soc_obj->dfs_psoc_nolinfo[pdev_id]; + /* Fetch the NOL entries for the DFS object. */ + dfs_getnol(dfs, &tmp_nolinfo); + + /* nolinfo might already have some data. Do not overwrite it */ + num_chans = nolinfo->dfs_ch_nchans; + for (i = 0; i < tmp_nolinfo.dfs_ch_nchans; i++) { + tmp_freq = tmp_nolinfo.dfs_nol[i].nol_freq; + + /* Add to nolinfo only if within the pdev's frequency range. */ + if ((low_5ghz_freq < tmp_freq) && (high_5ghz_freq > tmp_freq)) { + /* Figure out the completed duration of each NOL. */ + uint32_t nol_completed_ms = + qdf_system_ticks_to_msecs(qdf_system_ticks() - + tmp_nolinfo.dfs_nol[i].nol_start_ticks); + + nolinfo->dfs_nol[num_chans] = tmp_nolinfo.dfs_nol[i]; + /* Remember the remaining NOL time in the timeout + * variable. + */ + nolinfo->dfs_nol[num_chans++].nol_timeout_ms -= + nol_completed_ms; + } + } + + nolinfo->dfs_ch_nchans = num_chans; +} + +void dfs_reinit_nol_from_psoc_copy(struct wlan_dfs *dfs, uint8_t pdev_id) +{ + struct dfs_soc_priv_obj *dfs_soc_obj = dfs->dfs_soc_obj; + struct dfsreq_nolinfo *nol; + uint8_t i; + + if (!dfs_soc_obj->dfs_psoc_nolinfo) + return; + + if (!dfs_soc_obj->dfs_psoc_nolinfo[pdev_id].dfs_ch_nchans) + return; + + nol = &dfs_soc_obj->dfs_psoc_nolinfo[pdev_id]; + + /* The NOL timeout value in each entry points to the remaining time + * of the NOL. This is to indicate that the NOL entries are paused + * and are not left to continue. + * While adding these NOL, update the start ticks to current time + * to avoid losing entries which might have timed out during + * the pause and resume mechanism. + */ + for (i = 0; i < nol->dfs_ch_nchans; i++) + nol->dfs_nol[i].nol_start_ticks = qdf_system_ticks(); + dfs_set_nol(dfs, nol->dfs_nol, nol->dfs_ch_nchans); +} diff --git a/umac/dfs/core/src/misc/dfs_process_radar_found_ind.c b/umac/dfs/core/src/misc/dfs_process_radar_found_ind.c index bba638f946..6c02b7036b 100644 --- a/umac/dfs/core/src/misc/dfs_process_radar_found_ind.c +++ b/umac/dfs/core/src/misc/dfs_process_radar_found_ind.c @@ -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 @@ -951,16 +951,50 @@ QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs, bool wait_for_csa = false; uint16_t freq_list[NUM_CHANNELS_160MHZ]; uint8_t num_channels; - QDF_STATUS status; + QDF_STATUS status = QDF_STATUS_E_FAILURE; uint32_t freq_center; uint32_t radarfound_freq; struct dfs_channel *dfs_curchan; + /* Acquire a lock to avoid initiating mode switch till radar + * processing is completed. + */ + DFS_RADAR_MODE_SWITCH_LOCK(dfs); + + /* Before processing radar, check if HW mode switch is in progress. + * If in progress, defer the processing of radar event received till + * the mode switch is completed. + */ + if (dfs_is_hw_mode_switch_in_progress(dfs)) { + struct radar_found_info *radar_params = NULL; + + radar_params = qdf_mem_malloc(sizeof(*radar_params)); + if (!radar_params) + goto exit; + + /* If CAC timer is running, cancel it here rather than + * after processing to avoid handling unnecessary CAC timeouts. + */ + if (dfs->dfs_cac_timer_running) + dfs_cac_stop(dfs); + + /* If CAC timer is to be handled after mode switch and then + * we receive radar, no point in handling CAC completion. + */ + if (dfs->dfs_defer_params.is_cac_completed) + dfs->dfs_defer_params.is_cac_completed = false; + qdf_mem_copy(radar_params, radar_found, sizeof(*radar_params)); + dfs->dfs_defer_params.radar_params = radar_params; + dfs->dfs_defer_params.is_radar_detected = true; + status = QDF_STATUS_SUCCESS; + goto exit; + } + dfs_curchan = dfs->dfs_curchan; if (!dfs_curchan) { dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs->dfs_curchan is NULL"); - return QDF_STATUS_E_FAILURE; + goto exit; } /* Check if the current channel is a non DFS channel @@ -972,7 +1006,7 @@ QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs, !(radar_found->detector_id == AGILE_DETECTOR_ID)) { dfs_err(dfs, WLAN_DEBUG_DFS, "radar event on a non-DFS channel"); - return QDF_STATUS_E_FAILURE; + goto exit; } /* Sanity checks for radar on Agile detector */ @@ -981,7 +1015,7 @@ QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs, { dfs_err(dfs, WLAN_DEBUG_DFS, "radar on Agile detector when ADFS is not running"); - return QDF_STATUS_E_FAILURE; + goto exit; } /* For Full Offload, FW sends segment id,freq_offset and chirp @@ -1019,7 +1053,8 @@ QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs, if (!dfs->dfs_use_nol) { dfs_reset_bangradar(dfs); dfs_send_csa_to_current_chan(dfs); - return QDF_STATUS_SUCCESS; + status = QDF_STATUS_SUCCESS; + goto exit; } if (dfs->dfs_bangradar_type == DFS_BANGRADAR_FOR_ALL_SUBCHANS) @@ -1049,7 +1084,7 @@ QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs, if (QDF_IS_STATUS_ERROR(status)) { dfs_err(dfs, WLAN_DEBUG_DFS, "radar event received on invalid channel"); - return status; + goto exit; } dfs->dfs_is_nol_ie_sent = false; @@ -1105,7 +1140,7 @@ QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs, * channel change is not required. */ if (radar_found->detector_id == AGILE_DETECTOR_ID) - return QDF_STATUS_SUCCESS; + goto exit; if (!dfs->dfs_is_offload_enabled && dfs->is_radar_found_on_secondary_seg) { dfs_second_segment_radar_disable(dfs); @@ -1113,7 +1148,7 @@ QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs, if (dfs->is_radar_during_precac) { dfs->is_radar_during_precac = 0; - return QDF_STATUS_SUCCESS; + goto exit; } } @@ -1124,7 +1159,7 @@ QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs, * needs to be fixed. See EV 105776. */ if (wait_for_csa) - return QDF_STATUS_SUCCESS; + goto exit; /* * EV 129487 : We have detected radar in the channel, @@ -1144,6 +1179,8 @@ QDF_STATUS dfs_process_radar_ind(struct wlan_dfs *dfs, dfs->dfs_curchan->dfs_ch_mhz_freq_seg2, dfs->dfs_curchan->dfs_ch_flags); - return QDF_STATUS_SUCCESS; +exit: + DFS_RADAR_MODE_SWITCH_UNLOCK(dfs); + return status; } #endif diff --git a/umac/dfs/dispatcher/inc/wlan_dfs_ioctl.h b/umac/dfs/dispatcher/inc/wlan_dfs_ioctl.h index 1ec4e97c9c..a17d29b32d 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-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2011, 2016-2020 The Linux Foundation. All rights reserved. * Copyright (c) 2010, Atheros Communications Inc. * All Rights Reserved. * @@ -77,7 +77,7 @@ #define DFS_LAST_IOCTL 29 #ifndef DFS_CHAN_MAX -#define DFS_CHAN_MAX 1023 +#define DFS_CHAN_MAX 25 #endif /** diff --git a/umac/dfs/dispatcher/inc/wlan_dfs_lmac_api.h b/umac/dfs/dispatcher/inc/wlan_dfs_lmac_api.h index 99b671e915..5ed030da21 100644 --- a/umac/dfs/dispatcher/inc/wlan_dfs_lmac_api.h +++ b/umac/dfs/dispatcher/inc/wlan_dfs_lmac_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -118,4 +118,13 @@ static inline bool lmac_is_host_dfs_check_support_enabled( return false; } #endif + +/** + * lmac_dfs_is_hw_mode_switch_in_progress() - Check if HW mode switch is in + * progress. + * @pdev: Pointer to PDEV structure. + * + * Return: true if HW mode switch is in progress, else false. + */ +bool lmac_dfs_is_hw_mode_switch_in_progress(struct wlan_objmgr_pdev *pdev); #endif /* _WLAN_DFS_LMAC_API_H_ */ diff --git a/umac/dfs/dispatcher/inc/wlan_dfs_mlme_api.h b/umac/dfs/dispatcher/inc/wlan_dfs_mlme_api.h index f8d9a31523..3593f06d0f 100644 --- a/umac/dfs/dispatcher/inc/wlan_dfs_mlme_api.h +++ b/umac/dfs/dispatcher/inc/wlan_dfs_mlme_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -440,4 +440,22 @@ void dfs_mlme_handle_dfs_scan_violation(struct wlan_objmgr_pdev *pdev) * Return: true if pdev opmode is STA, else false. */ bool dfs_mlme_is_opmode_sta(struct wlan_objmgr_pdev *pdev); + +/** + * dfs_mlme_acquire_radar_mode_switch_lock() - Acquire lock for radar processing + * over mode switch handling. + * @pdev: Pointer to DFS pdev object. + * + * Return: void. + */ +void dfs_mlme_acquire_radar_mode_switch_lock(struct wlan_objmgr_pdev *pdev); + +/** + * dfs_mlme_release_radar_mode_switch_lock() - Release lock taken for radar + * processing over mode switch handling. + * @pdev: Pointer to DFS pdev object. + * + * Return: void. + */ +void dfs_mlme_release_radar_mode_switch_lock(struct wlan_objmgr_pdev *pdev); #endif /* _WLAN_DFS_MLME_API_H_ */ diff --git a/umac/dfs/dispatcher/inc/wlan_dfs_tgt_api.h b/umac/dfs/dispatcher/inc/wlan_dfs_tgt_api.h index 724dea5a7c..c49a497ae2 100644 --- a/umac/dfs/dispatcher/inc/wlan_dfs_tgt_api.h +++ b/umac/dfs/dispatcher/inc/wlan_dfs_tgt_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -604,4 +604,77 @@ void tgt_dfs_set_fw_adfs_support(struct wlan_objmgr_pdev *pdev, { } #endif + +/** + * tgt_dfs_init_tmp_psoc_nol() - Init temporary psoc NOL structure. + * @pdev: Pointer to pdev object. + * @num_radios: Number of radios in the psoc. + * + * Return: void. + */ +void tgt_dfs_init_tmp_psoc_nol(struct wlan_objmgr_pdev *pdev, + uint8_t num_radios); + +/** + * tgt_dfs_deinit_tmp_psoc_nol() - De-init temporary psoc NOL structure. + * @pdev: Pointer to pdev object. + * + * Return: void. + */ +void tgt_dfs_deinit_tmp_psoc_nol(struct wlan_objmgr_pdev *pdev); + +/** + * tgt_dfs_save_dfs_nol_in_psoc() - Save NOL data of given pdev. + * @pdev: Pointer to pdev object. + * @pdev_id: The pdev ID which will have the NOL data. + * @low_5ghz_freq: The low 5GHz frequency value of the target pdev id. + * @high_5ghz_freq: The high 5GHz frequency value of the target pdev id. + * + * Based on the frequency of the NOL channel, copy it to the target pdev_id + * structure in psoc. + * + * Return: void. + */ +void tgt_dfs_save_dfs_nol_in_psoc(struct wlan_objmgr_pdev *pdev, + uint8_t pdev_id, + uint16_t low_5ghz_freq, + uint16_t high_5ghz_freq); + +/** + * tgt_dfs_reinit_nol_from_psoc_copy() - Reinit saved NOL data to corresponding + * pdevs. + * @pdev: Pointer to pdev object. + * @pdev_id: pdev_id of the given pdev. + * + * Return: void. + */ +void tgt_dfs_reinit_nol_from_psoc_copy(struct wlan_objmgr_pdev *pdev, + uint8_t pdev_id); + +/** + * tgt_dfs_reinit_precac_lists() - Reinit preCAC lists. + * @src_pdev: Source pdev object from which the preCAC list is copied. + * @dest_pdev: Destination pdev object to which the preCAC list is copied. + * @low_5g_freq: Low 5G frequency value of the destination DFS. + * @high_5g_freq: High 5G frequency value of the destination DFS. + * + * Copy all the preCAC list entries from the source pdev object to the + * destination pdev object which fall within the frequency range of + * low_5g_freq and high_5g_freq. + * + * Return: None (void). + */ +void tgt_dfs_reinit_precac_lists(struct wlan_objmgr_pdev *src_pdev, + struct wlan_objmgr_pdev *dest_pdev, + uint16_t low_5g_freq, + uint16_t high_5g_freq); + +/** + * tgt_dfs_complete_deferred_tasks() - Process HW mode switch completion and + * handle deferred tasks. + * @pdev: Pointer to primary pdev object. + * + * Return: void. + */ +void tgt_dfs_complete_deferred_tasks(struct wlan_objmgr_pdev *pdev); #endif /* _WLAN_DFS_TGT_API_H_ */ diff --git a/umac/dfs/dispatcher/inc/wlan_dfs_ucfg_api.h b/umac/dfs/dispatcher/inc/wlan_dfs_ucfg_api.h index bbf9b0e9c7..2d7d7fb825 100644 --- a/umac/dfs/dispatcher/inc/wlan_dfs_ucfg_api.h +++ b/umac/dfs/dispatcher/inc/wlan_dfs_ucfg_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -73,6 +73,10 @@ * list. * @mlme_get_cac_timeout_for_freq: Get CAC timeout for a given channel * frequency. + * @mlme_acquire_radar_mode_switch_lock: Acquire lock for radar processing over + * mode switch. + * @mlme_release_radar_mode_switch_lock: Release lock taken for radar processing + * over mode switch. */ struct dfs_to_mlme { QDF_STATUS (*pdev_component_obj_attach)(struct wlan_objmgr_pdev *pdev, @@ -242,6 +246,10 @@ struct dfs_to_mlme { (struct wlan_objmgr_pdev *pdev, uint16_t freq, enum WLAN_DFS_EVENTS event); + void (*mlme_acquire_radar_mode_switch_lock) + (struct wlan_objmgr_pdev *pdev); + void (*mlme_release_radar_mode_switch_lock) + (struct wlan_objmgr_pdev *pdev); }; extern struct dfs_to_mlme global_dfs_to_mlme; diff --git a/umac/dfs/dispatcher/src/wlan_dfs_init_deinit_api.c b/umac/dfs/dispatcher/src/wlan_dfs_init_deinit_api.c index ee87b8dd06..db9cc0c7ab 100644 --- a/umac/dfs/dispatcher/src/wlan_dfs_init_deinit_api.c +++ b/umac/dfs/dispatcher/src/wlan_dfs_init_deinit_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -139,6 +139,10 @@ void register_dfs_callbacks(void) tmp_dfs_to_mlme->mlme_dfs_deliver_event = mlme_dfs_deliver_event; + tmp_dfs_to_mlme->mlme_acquire_radar_mode_switch_lock = + mlme_acquire_radar_mode_switch_lock; + tmp_dfs_to_mlme->mlme_release_radar_mode_switch_lock = + mlme_release_radar_mode_switch_lock; /* * Register precac auto channel switch feature related callbacks */ diff --git a/umac/dfs/dispatcher/src/wlan_dfs_lmac_api.c b/umac/dfs/dispatcher/src/wlan_dfs_lmac_api.c index bfa0b4ee4a..48c0bb454d 100644 --- a/umac/dfs/dispatcher/src/wlan_dfs_lmac_api.c +++ b/umac/dfs/dispatcher/src/wlan_dfs_lmac_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -197,3 +197,20 @@ bool lmac_is_host_dfs_check_support_enabled(struct wlan_objmgr_pdev *pdev) return enabled; } #endif + +bool lmac_dfs_is_hw_mode_switch_in_progress(struct wlan_objmgr_pdev *pdev) +{ + struct wlan_objmgr_psoc *psoc; + struct wlan_lmac_if_dfs_tx_ops *dfs_tx_ops; + bool is_hw_mode_switch_in_progress = false; + + psoc = wlan_pdev_get_psoc(pdev); + dfs_tx_ops = &psoc->soc_cb.tx_ops.dfs_tx_ops; + + if (dfs_tx_ops->dfs_check_mode_switch_state) + dfs_tx_ops->dfs_check_mode_switch_state( + pdev, + &is_hw_mode_switch_in_progress); + + return is_hw_mode_switch_in_progress; +} diff --git a/umac/dfs/dispatcher/src/wlan_dfs_mlme_api.c b/umac/dfs/dispatcher/src/wlan_dfs_mlme_api.c index d881a20506..54e68c6af7 100644 --- a/umac/dfs/dispatcher/src/wlan_dfs_mlme_api.c +++ b/umac/dfs/dispatcher/src/wlan_dfs_mlme_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -567,3 +567,19 @@ bool dfs_mlme_is_opmode_sta(struct wlan_objmgr_pdev *pdev) return global_dfs_to_mlme.mlme_is_opmode_sta(pdev); } + +void dfs_mlme_acquire_radar_mode_switch_lock(struct wlan_objmgr_pdev *pdev) +{ + if (!global_dfs_to_mlme.mlme_acquire_radar_mode_switch_lock) + return; + + global_dfs_to_mlme.mlme_acquire_radar_mode_switch_lock(pdev); +} + +void dfs_mlme_release_radar_mode_switch_lock(struct wlan_objmgr_pdev *pdev) +{ + if (!global_dfs_to_mlme.mlme_release_radar_mode_switch_lock) + return; + + global_dfs_to_mlme.mlme_release_radar_mode_switch_lock(pdev); +} diff --git a/umac/dfs/dispatcher/src/wlan_dfs_tgt_api.c b/umac/dfs/dispatcher/src/wlan_dfs_tgt_api.c index fc955e3925..577976dad0 100644 --- a/umac/dfs/dispatcher/src/wlan_dfs_tgt_api.c +++ b/umac/dfs/dispatcher/src/wlan_dfs_tgt_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -944,3 +944,102 @@ void tgt_dfs_set_fw_adfs_support(struct wlan_objmgr_pdev *pdev, qdf_export_symbol(tgt_dfs_set_fw_adfs_support); #endif + +void tgt_dfs_init_tmp_psoc_nol(struct wlan_objmgr_pdev *pdev, + uint8_t num_radios) +{ + struct wlan_dfs *dfs; + + dfs = wlan_pdev_get_dfs_obj(pdev); + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); + return; + } + + dfs_init_tmp_psoc_nol(dfs, num_radios); +} + +qdf_export_symbol(tgt_dfs_init_tmp_psoc_nol); + +void tgt_dfs_deinit_tmp_psoc_nol(struct wlan_objmgr_pdev *pdev) +{ + struct wlan_dfs *dfs; + + dfs = wlan_pdev_get_dfs_obj(pdev); + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); + return; + } + + dfs_deinit_tmp_psoc_nol(dfs); +} + +qdf_export_symbol(tgt_dfs_deinit_tmp_psoc_nol); + +void tgt_dfs_save_dfs_nol_in_psoc(struct wlan_objmgr_pdev *pdev, + uint8_t pdev_id, + uint16_t low_5ghz_freq, + uint16_t high_5ghz_freq) +{ + struct wlan_dfs *dfs; + + dfs = wlan_pdev_get_dfs_obj(pdev); + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); + return; + } + + dfs_save_dfs_nol_in_psoc(dfs, pdev_id, low_5ghz_freq, high_5ghz_freq); +} + +qdf_export_symbol(tgt_dfs_save_dfs_nol_in_psoc); + +void tgt_dfs_reinit_nol_from_psoc_copy(struct wlan_objmgr_pdev *pdev, + uint8_t pdev_id) +{ + struct wlan_dfs *dfs; + + dfs = wlan_pdev_get_dfs_obj(pdev); + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); + return; + } + + dfs_reinit_nol_from_psoc_copy(dfs, pdev_id); +} + +qdf_export_symbol(tgt_dfs_reinit_nol_from_psoc_copy); + +void tgt_dfs_reinit_precac_lists(struct wlan_objmgr_pdev *src_pdev, + struct wlan_objmgr_pdev *dest_pdev, + uint16_t low_5g_freq, + uint16_t high_5g_freq) +{ + struct wlan_dfs *src_dfs, *dest_dfs; + + src_dfs = wlan_pdev_get_dfs_obj(src_pdev); + if (!src_dfs) { + dfs_err(src_dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); + return; + } + dest_dfs = wlan_pdev_get_dfs_obj(dest_pdev); + if (!dest_dfs) { + dfs_err(dest_dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); + return; + } + + dfs_reinit_precac_lists(src_dfs, dest_dfs, low_5g_freq, high_5g_freq); +} + +void tgt_dfs_complete_deferred_tasks(struct wlan_objmgr_pdev *pdev) +{ + struct wlan_dfs *dfs; + + dfs = wlan_pdev_get_dfs_obj(pdev); + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); + return; + } + + dfs_complete_deferred_tasks(dfs); +} diff --git a/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h b/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h index 2e8c7a8ab9..0b3f839a86 100644 --- a/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h +++ b/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h @@ -802,6 +802,7 @@ struct wlan_lmac_if_reg_tx_ops { * @dfs_send_avg_radar_params_to_fw: Send average radar parameters to FW. * @dfs_send_usenol_pdev_param: Send usenol pdev param to FW. * @dfs_send_subchan_marking_pdev_param: Send subchan marking pdev param to FW. + * @dfs_check_mode_switch_state: Find if HW mode switch is in progress. */ struct wlan_lmac_if_dfs_tx_ops { @@ -855,6 +856,9 @@ struct wlan_lmac_if_dfs_tx_ops { QDF_STATUS (*dfs_send_subchan_marking_pdev_param)( struct wlan_objmgr_pdev *pdev, bool subchanmark); + QDF_STATUS (*dfs_check_mode_switch_state)( + struct wlan_objmgr_pdev *pdev, + bool *is_hw_mode_switch_in_progress); }; /** @@ -1356,6 +1360,12 @@ struct wlan_lmac_if_wifi_pos_rx_ops { * @dfs_is_hw_pulses_allowed: Check if HW pulses are allowed or not. * @dfs_set_fw_adfs_support: Set the agile DFS FW support in DFS. * @dfs_reset_dfs_prevchan: Reset DFS previous channel structure. + * @dfs_init_tmp_psoc_nol: Init temporary PSOC NOL structure. + * @dfs_deinit_tmp_psoc_nol: Deinit temporary PSOC NOL structure. + * @dfs_save_dfs_nol_in_psoc: Copy DFS NOL data to the PSOC copy. + * @dfs_reinit_nol_from_psoc_copy: Reinit DFS NOL from the PSOC NOL copy. + * @dfs_reinit_precac_lists: Reinit precac lists from other pdev. + * @dfs_complete_deferred_tasks: Process mode switch completion in DFS. */ struct wlan_lmac_if_dfs_rx_ops { QDF_STATUS (*dfs_get_radars)(struct wlan_objmgr_pdev *pdev); @@ -1523,6 +1533,20 @@ struct wlan_lmac_if_dfs_rx_ops { bool fw_adfs_support_160, bool fw_adfs_support_non_160); void (*dfs_reset_dfs_prevchan)(struct wlan_objmgr_pdev *pdev); + void (*dfs_init_tmp_psoc_nol)(struct wlan_objmgr_pdev *pdev, + uint8_t num_radios); + void (*dfs_deinit_tmp_psoc_nol)(struct wlan_objmgr_pdev *pdev); + void (*dfs_save_dfs_nol_in_psoc)(struct wlan_objmgr_pdev *pdev, + uint8_t pdev_id, + uint16_t low_5ghz_freq, + uint16_t high_5ghz_freq); + void (*dfs_reinit_nol_from_psoc_copy)(struct wlan_objmgr_pdev *pdev, + uint8_t pdev_id); + void (*dfs_reinit_precac_lists)(struct wlan_objmgr_pdev *src_pdev, + struct wlan_objmgr_pdev *dest_pdev, + uint16_t low_5g_freq, + uint16_t high_5g_freq); + void (*dfs_complete_deferred_tasks)(struct wlan_objmgr_pdev *pdev); }; /** diff --git a/umac/global_umac_dispatcher/lmac_if/src/wlan_lmac_if.c b/umac/global_umac_dispatcher/lmac_if/src/wlan_lmac_if.c index 4c8359dec7..cd8fdf12a2 100644 --- a/umac/global_umac_dispatcher/lmac_if/src/wlan_lmac_if.c +++ b/umac/global_umac_dispatcher/lmac_if/src/wlan_lmac_if.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -523,7 +523,18 @@ wlan_lmac_if_umac_dfs_rx_ops_register(struct wlan_lmac_if_rx_ops *rx_ops) tgt_dfs_set_fw_adfs_support; dfs_rx_ops->dfs_reset_dfs_prevchan = utils_dfs_reset_dfs_prevchan; - + dfs_rx_ops->dfs_init_tmp_psoc_nol = + tgt_dfs_init_tmp_psoc_nol; + dfs_rx_ops->dfs_deinit_tmp_psoc_nol = + tgt_dfs_deinit_tmp_psoc_nol; + dfs_rx_ops->dfs_save_dfs_nol_in_psoc = + tgt_dfs_save_dfs_nol_in_psoc; + dfs_rx_ops->dfs_reinit_nol_from_psoc_copy = + tgt_dfs_reinit_nol_from_psoc_copy; + dfs_rx_ops->dfs_reinit_precac_lists = + tgt_dfs_reinit_precac_lists; + dfs_rx_ops->dfs_complete_deferred_tasks = + tgt_dfs_complete_deferred_tasks; register_precac_auto_chan_rx_ops(dfs_rx_ops); register_precac_auto_chan_rx_ops_ieee(dfs_rx_ops); register_precac_auto_chan_rx_ops_freq(dfs_rx_ops); From 4120f06921ac573b4a402cefff1a3b3024e9edf6 Mon Sep 17 00:00:00 2001 From: Balamurugan Mahalingam Date: Fri, 27 Dec 2019 09:42:01 +0530 Subject: [PATCH 3/7] qcacmn: define SHADOW_REGISTER macro for QCN9000 Define shadow registers for QCN9000. Change-Id: I47fc7057838bf6491dc292660a69b47a655fe0e9 --- hal/wifi3.0/hal_api.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hal/wifi3.0/hal_api.h b/hal/wifi3.0/hal_api.h index 46fb142f34..616bab4b21 100644 --- a/hal/wifi3.0/hal_api.h +++ b/hal/wifi3.0/hal_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-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 @@ -32,7 +32,7 @@ #define SHADOW_REGISTER_END_ADDRESS_OFFSET \ ((SHADOW_REGISTER_START_ADDRESS_OFFSET) + (4 * (MAX_SHADOW_REGISTERS))) #define SHADOW_REGISTER(x) ((SHADOW_REGISTER_START_ADDRESS_OFFSET) + (4 * (x))) -#elif defined(QCA_WIFI_QCA6290) +#elif defined(QCA_WIFI_QCA6290) || defined(QCA_WIFI_QCN9000) #define SHADOW_REGISTER_START_ADDRESS_OFFSET 0x00003024 #define SHADOW_REGISTER_END_ADDRESS_OFFSET \ ((SHADOW_REGISTER_START_ADDRESS_OFFSET) + (4 * (MAX_SHADOW_REGISTERS))) From 8e63ff7840d66c2246dc5909a1d6537e9ca66e17 Mon Sep 17 00:00:00 2001 From: Daniel Kim Date: Tue, 7 Jan 2020 17:54:29 -0800 Subject: [PATCH 4/7] qcacmn: Use correct phy id in the reg services To support dynamic mode switch (phase 2), correct phy_id should be used. Instead of pdev_id, target phy_id should be used to retrieve correct channel range sent in target capabilities (mac_phy_caps). Change-Id: If0e2503cc99636b775721ecb3628290d19e5575c --- umac/regulatory/core/src/reg_services_common.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/umac/regulatory/core/src/reg_services_common.c b/umac/regulatory/core/src/reg_services_common.c index 1b61ab3fb5..a3040806e4 100644 --- a/umac/regulatory/core/src/reg_services_common.c +++ b/umac/regulatory/core/src/reg_services_common.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 @@ -34,6 +34,7 @@ #include "reg_db_parser.h" #include "reg_build_chan_list.h" #include +#include const struct chan_map *channel_map; #ifdef CONFIG_CHAN_NUM_API @@ -2654,11 +2655,13 @@ QDF_STATUS reg_modify_pdev_chan_range(struct wlan_objmgr_pdev *pdev) struct wlan_lmac_if_reg_tx_ops *reg_tx_ops; struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap_ptr; uint32_t cnt; - uint32_t pdev_id; + uint32_t phy_id; enum direction dir; QDF_STATUS status = QDF_STATUS_SUCCESS; + struct target_pdev_info *tgt_pdev; - pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); + tgt_pdev = wlan_pdev_get_tgt_if_handle(pdev); + phy_id = (uint32_t)target_pdev_get_phy_idx(tgt_pdev); pdev_priv_obj = reg_get_pdev_obj(pdev); if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) { reg_err("pdev reg component is NULL"); @@ -2686,7 +2689,7 @@ QDF_STATUS reg_modify_pdev_chan_range(struct wlan_objmgr_pdev *pdev) return QDF_STATUS_E_FAULT; } - if (reg_cap_ptr->phy_id == pdev_id) + if (reg_cap_ptr->phy_id == phy_id) break; reg_cap_ptr++; } From d207ff2e28c62fa787d6733df0fd8576508aa5d7 Mon Sep 17 00:00:00 2001 From: Sravan Goud Date: Thu, 19 Dec 2019 23:58:15 +0530 Subject: [PATCH 5/7] qcacmn: Provide vendor extended stats from host Currently in lithium FW is not always in datapath. As a result can not provide all the wlan vendor extended stats. So as part of this host provides some of the extended stats. Change-Id: I876b6e905f7e25b7088f80f07e55e26a7a409241 CRs-Fixed: 2594797 --- dp/inc/cdp_txrx_misc.h | 69 +++++++++++++++- dp/inc/cdp_txrx_mob_def.h | 20 ++++- dp/inc/cdp_txrx_ops.h | 5 ++ dp/wifi3.0/dp_main.c | 169 ++++++++++++++++++++++++++++++++++++++ dp/wifi3.0/dp_types.h | 11 +++ 5 files changed, 272 insertions(+), 2 deletions(-) diff --git a/dp/inc/cdp_txrx_misc.h b/dp/inc/cdp_txrx_misc.h index 461130a31e..5c209565a4 100644 --- a/dp/inc/cdp_txrx_misc.h +++ b/dp/inc/cdp_txrx_misc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-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 @@ -747,4 +747,71 @@ static inline void cdp_pdev_reset_bundle_require_flag(ol_txrx_soc_handle soc, return soc->ops->misc_ops->pdev_reset_bundle_require_flag( soc, pdev_id); } + +/** + * cdp_txrx_ext_stats_request(): request dp tx and rx extended stats + * @soc: soc handle + * @pdev_id: pdev id + * @req: stats request structure to fill + * + * return: status + */ +static inline QDF_STATUS +cdp_txrx_ext_stats_request(ol_txrx_soc_handle soc, uint8_t pdev_id, + struct cdp_txrx_ext_stats *req) +{ + if (!soc || !soc->ops || !soc->ops->misc_ops || !req) { + QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, + "%s: Invalid Instance:", __func__); + return QDF_STATUS_E_INVAL; + } + + if (soc->ops->misc_ops->txrx_ext_stats_request) + return soc->ops->misc_ops->txrx_ext_stats_request(soc, pdev_id, + req); + + return QDF_STATUS_SUCCESS; +} + +/** + * cdp_request_rx_hw_stats(): request rx hw stats + * @soc: soc handle + * @vdev_id: vdev id + * + * return: none + */ +static inline void +cdp_request_rx_hw_stats(ol_txrx_soc_handle soc, uint8_t vdev_id) +{ + if (!soc || !soc->ops || !soc->ops->misc_ops) { + QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, + "%s: Invalid Instance:", __func__); + return; + } + + if (soc->ops->misc_ops->request_rx_hw_stats) + soc->ops->misc_ops->request_rx_hw_stats(soc, vdev_id); +} + +/** + * cdp_wait_for_ext_rx_stats(): wait for reo command status for stats + * @soc: soc handle + * + * return: status + */ +static inline QDF_STATUS +cdp_wait_for_ext_rx_stats(ol_txrx_soc_handle soc) +{ + if (!soc || !soc->ops || !soc->ops->misc_ops) { + QDF_TRACE(QDF_MODULE_ID_CDP, QDF_TRACE_LEVEL_DEBUG, + "%s: Invalid Instance:", __func__); + return QDF_STATUS_E_INVAL; + } + + if (soc->ops->misc_ops->wait_for_ext_rx_stats) + return soc->ops->misc_ops->wait_for_ext_rx_stats(soc); + + return QDF_STATUS_SUCCESS; +} + #endif /* _CDP_TXRX_MISC_H_ */ diff --git a/dp/inc/cdp_txrx_mob_def.h b/dp/inc/cdp_txrx_mob_def.h index 2550bb82e8..e91753bb72 100644 --- a/dp/inc/cdp_txrx_mob_def.h +++ b/dp/inc/cdp_txrx_mob_def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-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 @@ -471,4 +471,22 @@ struct ol_rx_inv_peer_params { uint8_t ta[QDF_MAC_ADDR_SIZE]; }; +/** + * cdp_txrx_ext_stats: dp extended stats + * tx_msdu_enqueue: tx msdu queued to hw + * tx_msdu_overflow: tx msdu overflow + * rx_mpdu_received: rx mpdu processed by hw + * rx_mpdu_delivered: rx mpdu received from hw + * rx_mpdu_error: rx mpdu error count + * rx_mpdu_missed: rx mpdu missed by hw + */ +struct cdp_txrx_ext_stats { + uint32_t tx_msdu_enqueue; + uint32_t tx_msdu_overflow; + uint32_t rx_mpdu_received; + uint32_t rx_mpdu_delivered; + uint32_t rx_mpdu_error; + uint32_t rx_mpdu_missed; +}; + #endif /* __CDP_TXRX_MOB_DEF_H */ diff --git a/dp/inc/cdp_txrx_ops.h b/dp/inc/cdp_txrx_ops.h index 372d5dcde4..22346cc58b 100644 --- a/dp/inc/cdp_txrx_ops.h +++ b/dp/inc/cdp_txrx_ops.h @@ -1238,6 +1238,11 @@ struct cdp_misc_ops { uint32_t low_th); void (*pdev_reset_bundle_require_flag)(struct cdp_soc_t *soc_hdl, uint8_t pdev_id); + QDF_STATUS (*txrx_ext_stats_request)(struct cdp_soc_t *soc_hdl, + uint8_t pdev_id, + struct cdp_txrx_ext_stats *req); + void (*request_rx_hw_stats)(struct cdp_soc_t *soc_hdl, uint8_t vdev_id); + QDF_STATUS (*wait_for_ext_rx_stats)(struct cdp_soc_t *soc_hdl); }; /** diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 769c4f9546..7a969ac481 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -2807,6 +2807,17 @@ static void dp_enable_verbose_debug(struct dp_soc *soc) } #endif +#ifdef WLAN_FEATURE_STATS_EXT +static inline void dp_create_ext_stats_event(struct dp_soc *soc) +{ + qdf_event_create(&soc->rx_hw_stats_event); +} +#else +static inline void dp_create_ext_stats_event(struct dp_soc *soc) +{ +} +#endif + /* * dp_soc_cmn_setup() - Common SoC level initializion * @soc: Datapath SOC handle @@ -3055,6 +3066,7 @@ static int dp_soc_cmn_setup(struct dp_soc *soc) wlan_cfg_get_defrag_timeout_check(soc_cfg_ctx); qdf_spinlock_create(&soc->rx.defrag.defrag_lock); + dp_create_ext_stats_event(soc); out: /* * set the fragment destination ring @@ -5302,6 +5314,26 @@ static inline void dp_peer_rx_bufq_resources_init(struct dp_peer *peer) } #endif +#ifdef WLAN_FEATURE_STATS_EXT +/* + * dp_set_ignore_reo_status_cb() - set ignore reo status cb flag + * @soc: dp soc handle + * @flag: flag to set or reset + * + * Return: None + */ +static inline void dp_set_ignore_reo_status_cb(struct dp_soc *soc, + bool flag) +{ + soc->ignore_reo_status_cb = flag; +} +#else +static inline void dp_set_ignore_reo_status_cb(struct dp_soc *soc, + bool flag) +{ +} +#endif + /* * dp_peer_create_wifi3() - attach txrx peer * @soc_hdl: Datapath soc handle @@ -5458,6 +5490,12 @@ static void *dp_peer_create_wifi3(struct cdp_soc_t *soc_hdl, uint8_t vdev_id, vdev->vap_self_peer = peer; } + if (wlan_op_mode_sta == vdev->opmode && + qdf_mem_cmp(peer->mac_addr.raw, vdev->mac_addr.raw, + QDF_MAC_ADDR_SIZE) != 0) { + dp_set_ignore_reo_status_cb(soc, false); + } + for (i = 0; i < DP_MAX_TIDS; i++) qdf_spinlock_create(&peer->rx_tid[i].tid_lock); @@ -6244,6 +6282,12 @@ static QDF_STATUS dp_peer_delete_wifi3(struct cdp_soc_t *soc, uint8_t vdev_id, qdf_spinlock_destroy(&peer->peer_info_lock); dp_peer_multipass_list_remove(peer); + if (wlan_op_mode_sta == peer->vdev->opmode && + qdf_mem_cmp(peer->mac_addr.raw, peer->vdev->mac_addr.raw, + QDF_MAC_ADDR_SIZE) != 0) { + dp_set_ignore_reo_status_cb(peer->vdev->pdev->soc, true); + } + /* * Remove the reference added during peer_attach. * The peer will still be left allocated until the @@ -9983,6 +10027,125 @@ dp_txrx_post_data_stall_event(struct cdp_soc_t *soc_hdl, } #endif /* WLAN_SUPPORT_DATA_STALL */ +#ifdef WLAN_FEATURE_STATS_EXT +/* rx hw stats event wait timeout in ms */ +#define DP_REO_STATUS_STATS_TIMEOUT 1000 +/** + * dp_txrx_ext_stats_request - request dp txrx extended stats request + * @soc_hdl: soc handle + * @pdev_id: pdev id + * @req: stats request + * + * Return: QDF_STATUS + */ +static QDF_STATUS +dp_txrx_ext_stats_request(struct cdp_soc_t *soc_hdl, uint8_t pdev_id, + struct cdp_txrx_ext_stats *req) +{ + struct dp_soc *soc = (struct dp_soc *)soc_hdl; + struct dp_pdev *pdev = dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id); + + if (!pdev) { + dp_err("pdev is null"); + return QDF_STATUS_E_INVAL; + } + + dp_aggregate_pdev_stats(pdev); + + req->tx_msdu_enqueue = pdev->stats.tx_i.processed.num; + req->tx_msdu_overflow = pdev->stats.tx_i.dropped.ring_full; + req->rx_mpdu_received = soc->ext_stats.rx_mpdu_received; + req->rx_mpdu_delivered = soc->ext_stats.rx_mpdu_received; + req->rx_mpdu_missed = soc->ext_stats.rx_mpdu_missed; + req->rx_mpdu_error = soc->stats.rx.err_ring_pkts - + soc->stats.rx.rx_frags; + + return QDF_STATUS_SUCCESS; +} + +/** + * dp_rx_hw_stats_cb - request rx hw stats response callback + * @soc: soc handle + * @cb_ctxt: callback context + * @reo_status: reo command response status + * + * Return: None + */ +static void dp_rx_hw_stats_cb(struct dp_soc *soc, void *cb_ctxt, + union hal_reo_status *reo_status) +{ + struct dp_rx_tid *rx_tid = (struct dp_rx_tid *)cb_ctxt; + struct hal_reo_queue_status *queue_status = &reo_status->queue_status; + + if (soc->ignore_reo_status_cb) { + qdf_event_set(&soc->rx_hw_stats_event); + return; + } + + if (queue_status->header.status != HAL_REO_CMD_SUCCESS) { + dp_info("REO stats failure %d for TID %d", + queue_status->header.status, rx_tid->tid); + return; + } + + soc->ext_stats.rx_mpdu_received += queue_status->mpdu_frms_cnt; + soc->ext_stats.rx_mpdu_missed += queue_status->late_recv_mpdu_cnt; + + if (rx_tid->tid == (DP_MAX_TIDS - 1)) + qdf_event_set(&soc->rx_hw_stats_event); +} + +/** + * dp_request_rx_hw_stats - request rx hardware stats + * @soc_hdl: soc handle + * @vdev_id: vdev id + * + * Return: None + */ +static void +dp_request_rx_hw_stats(struct cdp_soc_t *soc_hdl, uint8_t vdev_id) +{ + struct dp_soc *soc = (struct dp_soc *)soc_hdl; + struct dp_vdev *vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id); + struct dp_peer *peer; + + if (!vdev) { + dp_err("vdev is null"); + qdf_event_set(&soc->rx_hw_stats_event); + return; + } + + peer = vdev->vap_bss_peer; + + if (!peer || peer->delete_in_progress) { + dp_err("Peer deletion in progress"); + qdf_event_set(&soc->rx_hw_stats_event); + return; + } + + qdf_event_reset(&soc->rx_hw_stats_event); + dp_peer_rxtid_stats(peer, dp_rx_hw_stats_cb, NULL); +} + +/** + * dp_wait_for_ext_rx_stats - wait for rx reo status for rx stats + * @soc_hdl: cdp opaque soc handle + * + * Return: status + */ +static QDF_STATUS +dp_wait_for_ext_rx_stats(struct cdp_soc_t *soc_hdl) +{ + struct dp_soc *soc = (struct dp_soc *)soc_hdl; + QDF_STATUS status; + + status = qdf_wait_single_event(&soc->rx_hw_stats_event, + DP_REO_STATUS_STATS_TIMEOUT); + + return status; +} +#endif /* WLAN_FEATURE_STATS_EXT */ + #ifdef DP_PEER_EXTENDED_API static struct cdp_misc_ops dp_ops_misc = { #ifdef FEATURE_WLAN_TDLS @@ -10002,6 +10165,12 @@ static struct cdp_misc_ops dp_ops_misc = { .txrx_data_stall_cb_deregister = dp_deregister_data_stall_detect_cb, .txrx_post_data_stall_event = dp_txrx_post_data_stall_event, #endif + +#ifdef WLAN_FEATURE_STATS_EXT + .txrx_ext_stats_request = dp_txrx_ext_stats_request, + .request_rx_hw_stats = dp_request_rx_hw_stats, + .wait_for_ext_rx_stats = dp_wait_for_ext_rx_stats, +#endif }; #endif diff --git a/dp/wifi3.0/dp_types.h b/dp/wifi3.0/dp_types.h index 9ec74261b3..37c3e07cbb 100644 --- a/dp/wifi3.0/dp_types.h +++ b/dp/wifi3.0/dp_types.h @@ -1163,6 +1163,17 @@ struct dp_soc { qdf_atomic_t ipa_pipes_enabled; #endif +#ifdef WLAN_FEATURE_STATS_EXT + struct { + uint32_t rx_mpdu_received; + uint32_t rx_mpdu_missed; + } ext_stats; + qdf_event_t rx_hw_stats_event; + + /* Ignore reo command queue status during peer delete */ + bool ignore_reo_status_cb; +#endif + /* Smart monitor capability for HKv2 */ uint8_t hw_nac_monitor_support; /* Flag to indicate if HTT v2 is enabled*/ From 5d2b019ea457e47214657eb18b8db14d3feccb28 Mon Sep 17 00:00:00 2001 From: Jinwei Chen Date: Wed, 8 Jan 2020 22:06:15 +0800 Subject: [PATCH 6/7] qcacmn: WAR for monitor mode HTT msg sending failure If two back to back HTT msg sending happened in short time, the second HTT msg source SRNG HP writing has chance to fail, this has been confirmed by HST HW. For monitor mode, HTT msg for monitor status ring configuration is the last msg for sending, if the 2nd HTT msg for monitor status ring sending failed, HW won't provide anything into 2nd monitor status ring. as a WAR, add some delay before 2nd HTT msg start sending, > 2us is required per HST HW, delay 100 us for safe. Change-Id: Id2a5a8798fde79267f9d6f9ba23d8ed54a400aa7 CRs-Fixed: 2597248 --- dp/wifi3.0/dp_main.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 7a969ac481..8cb11ade5c 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -6713,6 +6713,19 @@ QDF_STATUS dp_pdev_configure_monitor_rings(struct dp_pdev *pdev) for (mac_id = 0; mac_id < NUM_RXDMA_RINGS_PER_PDEV; mac_id++) { int mac_for_pdev = dp_get_mac_id_for_pdev(mac_id, pdev->pdev_id); + /* + * If two back to back HTT msg sending happened in + * short time, the second HTT msg source SRNG HP + * writing has chance to fail, this has been confirmed + * by HST HW. + * for monitor mode, here is the last HTT msg for sending. + * if the 2nd HTT msg for monitor status ring sending failed, + * HW won't provide anything into 2nd monitor status ring. + * as a WAR, add some delay before 2nd HTT msg start sending, + * > 2us is required per HST HW, delay 100 us for safe. + */ + if (mac_id) + qdf_udelay(100); htt_h2t_rx_ring_cfg(soc->htt_handle, mac_for_pdev, pdev->rxdma_mon_status_ring[mac_id].hal_srng, From c064fc3b4a54aa0649f7239729482d0b468b6063 Mon Sep 17 00:00:00 2001 From: Sravan Goud Date: Wed, 8 Jan 2020 19:49:59 +0530 Subject: [PATCH 7/7] qcacmn: Reduce excessive console logging There is excessive console logging in case of peer or vdev null in mic error handling and wbm err processing in softirq context which is delaying the interrupt to get enable and as a result host is slow in reaping the wbm2sw3 ring. This leads to wbm2sw3 ring full back pressure at FW and finally FW asserts. As part of this change reduce reduce the error logging level from err to info and for MSM info goes to the wifi logger logs and not to the console. Change-Id: I9b8be1feee5e807cecbe307b24a323e2b0ae631a CRs-Fixed: 2596656 --- dp/wifi3.0/dp_rx_err.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/dp/wifi3.0/dp_rx_err.c b/dp/wifi3.0/dp_rx_err.c index 29fd9acb6f..f036732423 100644 --- a/dp/wifi3.0/dp_rx_err.c +++ b/dp/wifi3.0/dp_rx_err.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-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 @@ -1101,19 +1101,19 @@ void dp_rx_process_mic_error(struct dp_soc *soc, qdf_nbuf_t nbuf, return; if (!peer) { - dp_err_rl("peer not found"); + dp_info_rl("peer not found"); goto fail; } vdev = peer->vdev; if (!vdev) { - dp_err_rl("VDEV not found"); + dp_info_rl("VDEV not found"); goto fail; } pdev = vdev->pdev; if (!pdev) { - dp_err_rl("PDEV not found"); + dp_info_rl("PDEV not found"); goto fail; } @@ -1516,9 +1516,9 @@ done: peer = dp_peer_find_by_id(soc, peer_id); if (!peer) - dp_err_rl("peer is null! peer_id %u err_src %u err_rsn %u", - peer_id, wbm_err_info.wbm_err_src, - wbm_err_info.reo_psh_rsn); + dp_info_rl("peer is null peer_id%u err_src%u err_rsn%u", + peer_id, wbm_err_info.wbm_err_src, + wbm_err_info.reo_psh_rsn); /* Set queue_mapping in nbuf to 0 */ dp_set_rx_queue(nbuf, 0); @@ -1583,8 +1583,8 @@ done: break; default: - dp_err_rl("Got pkt with REO ERROR: %d", - wbm_err_info.reo_err_code); + dp_info_rl("Got pkt with REO ERROR: %d", + wbm_err_info.reo_err_code); break; } }