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
Bu işleme şunda yer alıyor:
Vignesh Mohan
2019-10-23 17:34:14 +05:30
işlemeyi yapan: nshrivas
ebeveyn 79b64ac4ba
işleme 86eba5902e
17 değiştirilmiş dosya ile 618 ekleme ve 40 silme

Dosyayı Görüntüle

@@ -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
/**

Dosyayı Görüntüle

@@ -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_ */

Dosyayı Görüntüle

@@ -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_ */

Dosyayı Görüntüle

@@ -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_ */

Dosyayı Görüntüle

@@ -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;

Dosyayı Görüntüle

@@ -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
*/

Dosyayı Görüntüle

@@ -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;
}

Dosyayı Görüntüle

@@ -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);
}

Dosyayı Görüntüle

@@ -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);
}