Merge "qca-wifi-oss: Design a unified SM for Agile PreCAC and RCAC"

This commit is contained in:
Linux Build Service Account
2020-08-04 08:07:37 -07:00
committato da Gerrit - the friendly Code Review server

Vedi File

@@ -579,11 +579,30 @@ static void dfs_fill_adfs_chan_params(struct wlan_dfs *dfs,
adfs_param->precac_chwidth = dfs->dfs_precac_chwidth;
}
/* dfs_agile_precac_cleanup() - Reset parameters of wlan_dfs.
*
* @dfs: Pointer to struct wlan_dfs.
*/
static void dfs_agile_precac_cleanup(struct wlan_dfs *dfs)
{
struct dfs_soc_priv_obj *dfs_soc_obj;
dfs_soc_obj = dfs->dfs_soc_obj;
qdf_timer_sync_cancel(&dfs_soc_obj->dfs_precac_timer);
dfs_soc_obj->dfs_precac_timer_running = 0;
dfs_soc_obj->precac_state_started = 0;
dfs->dfs_agile_precac_freq_mhz = 0;
dfs->dfs_precac_chwidth = CH_WIDTH_INVALID;
dfs_soc_obj->cur_agile_dfs_index = DFS_PSOC_NO_IDX;
}
/*
* dfs_prepare_agile_precac_chan() - Prepare an agile channel for preCAC.
* @dfs: Pointer to wlan_dfs.
*
* Return Type: void
*/
void dfs_prepare_agile_precac_chan(struct wlan_dfs *dfs)
void dfs_prepare_agile_precac_chan(struct wlan_dfs *dfs, bool *is_chan_found)
{
struct wlan_objmgr_psoc *psoc;
struct wlan_objmgr_pdev *pdev;
@@ -651,9 +670,10 @@ void dfs_prepare_agile_precac_chan(struct wlan_dfs *dfs)
else
dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS,
"dfs_tx_ops=%pK", dfs_tx_ops);
*is_chan_found = true;
} else {
dfs->dfs_soc_obj->precac_state_started = false;
qdf_info("No channels in preCAC required list");
dfs_agile_precac_cleanup(dfs);
*is_chan_found = false;
}
}
#endif
@@ -872,6 +892,10 @@ static void dfs_unmark_rcac_done(struct wlan_dfs *dfs)
}
PRECAC_LIST_UNLOCK(dfs);
}
#else
static inline void dfs_unmark_rcac_done(struct wlan_dfs *dfs)
{
}
#endif
/*
@@ -1051,14 +1075,6 @@ void dfs_unmark_precac_nol_for_freq(struct wlan_dfs *dfs, uint16_t chan_freq)
dfs_mlme_channel_change_by_precac(
dfs->dfs_pdev_obj);
}
} else if (dfs_is_agile_precac_enabled(dfs) &&
!dfs->dfs_soc_obj->precac_state_started) {
/* precac_state_started will be set to false if
* agile CAC is not begun for any channels or
* all channels were CACed. If it's not set, defer
* changing the current Agile CAC channel.
*/
dfs_prepare_agile_precac_chan(dfs);
}
}
}
@@ -1157,41 +1173,6 @@ void dfs_mark_precac_nol_for_freq(struct wlan_dfs *dfs,
dfs->dfs_pdev_obj);
}
}
} else if (dfs_is_agile_precac_enabled(dfs)) {
/* If preCAC is not running on the DFS where radar is detected,
* no need to configure agile channel.
* Return from this function.
*/
if (!(dfs_soc_obj->cur_agile_dfs_index == dfs->dfs_psoc_idx)) {
dfs_debug(dfs, WLAN_DEBUG_DFS,
"preCAC not running on radarfound DFS idx=%d",
dfs->dfs_psoc_idx);
return;
}
qdf_timer_sync_cancel(&dfs_soc_obj->dfs_precac_timer);
dfs_soc_obj->dfs_precac_timer_running = 0;
/* Since Agile DFS is interrupted due to radar, send
* OCAC abort event to FW for a proper restart of the Agile
* state machine.
*/
if (dfs_tx_ops && dfs_tx_ops->dfs_ocac_abort_cmd)
dfs_tx_ops->dfs_ocac_abort_cmd(pdev);
/*
* If radar is found on agile engine, change the channel here
* since primary channel change will not be triggered.
* If radar is found on primary detector, let agile
* channel change be triggered after start response.
* Set precac_state_started to false to indicate preCAC is not
* running and also reset the current Agile channel.
*/
if (detector_id == dfs_get_agile_detector_id(dfs)) {
dfs_prepare_agile_precac_chan(dfs);
} else {
dfs->dfs_agile_precac_freq_mhz = 0;
dfs_soc_obj->precac_state_started = PRECAC_NOT_STARTED;
}
}
}
@@ -1266,9 +1247,10 @@ void dfs_process_ocac_complete(struct wlan_objmgr_pdev *pdev,
enum phy_ch_width chwidth)
{
struct wlan_dfs *dfs = NULL;
struct dfs_agile_cac_params adfs_param;
struct dfs_soc_priv_obj *dfs_soc_obj;
dfs = wlan_pdev_get_dfs_obj(pdev);
dfs_soc_obj = dfs->dfs_soc_obj;
/* When the FW sends a delayed OCAC completion status, Host might
* have changed the precac channel already before an OCAC
@@ -1294,12 +1276,9 @@ void dfs_process_ocac_complete(struct wlan_objmgr_pdev *pdev,
return;
}
/* STOP TIMER irrespective of status */
utils_dfs_cancel_precac_timer(pdev);
if (ocac_status == OCAC_RESET) {
dfs_debug(NULL, WLAN_DEBUG_DFS_ALWAYS,
"PreCAC timer reset, Sending Agile chan set command");
dfs_prepare_agile_precac_chan(dfs);
} else if (ocac_status == OCAC_CANCEL) {
dfs_debug(NULL, WLAN_DEBUG_DFS_ALWAYS,
"PreCAC timer abort, agile precac stopped");
@@ -1308,19 +1287,14 @@ void dfs_process_ocac_complete(struct wlan_objmgr_pdev *pdev,
"PreCAC timer Completed for agile freq: %d %d",
center_freq_mhz1,
center_freq_mhz2);
/*
* TRIGGER agile precac timer with 0sec timeout
* with ocac_status 0 for old pdev
*/
adfs_param.precac_center_freq_1 = center_freq_mhz1;
adfs_param.precac_center_freq_2 = center_freq_mhz2;
adfs_param.precac_chwidth = dfs->dfs_precac_chwidth;
dfs_start_agile_precac_timer(dfs,
ocac_status,
&adfs_param);
} else {
dfs_debug(NULL, WLAN_DEBUG_DFS_ALWAYS, "Error Unknown");
}
dfs_soc_obj->ocac_status = ocac_status;
dfs_agile_sm_deliver_evt(dfs_soc_obj,
DFS_AGILE_SM_EV_AGILE_DONE,
0, (void *)dfs);
}
#endif
#endif
@@ -1494,22 +1468,9 @@ static os_timer_func(dfs_precac_timeout)
"Pre-cac expired, Agile Precac chan %u curr time %d",
dfs->dfs_agile_precac_freq_mhz,
current_time / 1000);
if (dfs_soc_obj->ocac_status == OCAC_SUCCESS) {
dfs_soc_obj->ocac_status = OCAC_RESET;
dfs_mark_adfs_chan_as_cac_done(dfs);
}
/* check if CAC done on home channel */
is_cac_done_on_des_chan = dfs_precac_check_home_chan_change(dfs);
if (!is_cac_done_on_des_chan) {
/*
* Use same home channel, only change preCAC channel.
*/
/*
* TO BE DONE xxx : Need to lock the channel change.
*/
dfs_prepare_agile_precac_chan(dfs);
}
dfs_agile_sm_deliver_evt(dfs_soc_obj,
DFS_AGILE_SM_EV_AGILE_DONE,
0, (void *)dfs);
}
}
@@ -2681,24 +2642,18 @@ void dfs_start_agile_precac_timer(struct wlan_dfs *dfs,
dfs_soc_obj = dfs->dfs_soc_obj;
dfs_soc_obj->dfs_precac_timer_running = 1;
if (ocac_status == OCAC_SUCCESS) {
dfs_soc_obj->ocac_status = OCAC_SUCCESS;
min_precac_timeout = 0;
max_precac_timeout = 0;
/* Find the minimum and maximum precac timeout. */
max_precac_timeout = MAX_PRECAC_DURATION;
if (dfs->dfs_precac_timeout_override != -1) {
min_precac_timeout =
dfs->dfs_precac_timeout_override * 1000;
} else if (dfs_is_pcac_on_weather_channel_for_freq(dfs,
chwidth,
pcacfreq)) {
min_precac_timeout = MIN_WEATHER_PRECAC_DURATION;
max_precac_timeout = MAX_WEATHER_PRECAC_DURATION;
} else {
/* Find the minimum and maximum precac timeout. */
max_precac_timeout = MAX_PRECAC_DURATION;
if (dfs->dfs_precac_timeout_override != -1) {
min_precac_timeout =
dfs->dfs_precac_timeout_override * 1000;
} else if (dfs_is_pcac_on_weather_channel_for_freq(dfs,
chwidth,
pcacfreq)) {
min_precac_timeout = MIN_WEATHER_PRECAC_DURATION;
max_precac_timeout = MAX_WEATHER_PRECAC_DURATION;
} else {
min_precac_timeout = MIN_PRECAC_DURATION;
}
min_precac_timeout = MIN_PRECAC_DURATION;
}
dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
@@ -3271,9 +3226,8 @@ static void dfs_fill_des_rcac_chan_params(struct wlan_dfs *dfs,
ch_params->mhz_freq_seg0 = chan->dfs_ch_mhz_freq_seg1;
ch_params->mhz_freq_seg1 = chan->dfs_ch_mhz_freq_seg2;
}
#endif
#ifdef QCA_SUPPORT_ADFS_RCAC
bool dfs_is_agile_rcac_enabled(struct wlan_dfs *dfs)
{
enum dfs_reg dfsdomain;
@@ -3290,6 +3244,14 @@ bool dfs_is_agile_rcac_enabled(struct wlan_dfs *dfs)
}
#endif
#ifdef QCA_SUPPORT_AGILE_DFS
bool dfs_is_agile_cac_enabled(struct wlan_dfs *dfs)
{
return (dfs_is_agile_precac_enabled(dfs) ||
dfs_is_agile_rcac_enabled(dfs));
}
#endif
/* dfs_convert_chwidth_to_wlan_phymode() - Given a channel width, find out the
* 11AXA channel mode.
* @chwidth: Channel width of type enum phy_ch_width.
@@ -3928,8 +3890,16 @@ void dfs_set_precac_enable(struct wlan_dfs *dfs, uint32_t value)
if (dfs_is_precac_timer_running(dfs)) {
dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS,
"Precac flag changed. Cancel the precac timer");
dfs_cancel_precac_timer(dfs);
dfs->dfs_soc_obj->precac_state_started = 0;
if (tgt_tx_ops->tgt_is_tgt_type_qca9984(target_type)) {
dfs_cancel_precac_timer(dfs);
dfs->dfs_soc_obj->precac_state_started = 0;
} else {
#ifdef QCA_SUPPORT_AGILE_DFS
dfs_agile_sm_deliver_evt(dfs->dfs_soc_obj,
DFS_AGILE_SM_EV_AGILE_STOP,
0, (void *)dfs);
#endif
}
}
}
@@ -4091,7 +4061,7 @@ void dfs_reinit_precac_lists(struct wlan_dfs *src_dfs,
PRECAC_LIST_UNLOCK(dest_dfs);
}
#ifdef QCA_SUPPORT_ADFS_RCAC
#ifdef QCA_SUPPORT_AGILE_DFS
/* dfs_start_agile_engine() - Prepare ADFS params and program the agile
* engine sending agile config cmd to FW.
* @dfs: Pointer to struct wlan_dfs.
@@ -4330,6 +4300,7 @@ QDF_STATUS dfs_agile_sm_deliver_event(struct dfs_soc_priv_obj *dfs_soc_obj,
event_data);
}
#ifdef QCA_SUPPORT_ADFS_RCAC
/* dfs_start_agile_rcac_timer() - Start host agile RCAC timer.
*
* @dfs: Pointer to struct wlan_dfs.
@@ -4359,6 +4330,11 @@ void dfs_stop_agile_rcac_timer(struct wlan_dfs *dfs)
qdf_timer_sync_cancel(&dfs_soc_obj->dfs_rcac_timer);
}
/**
* dfs_abort_agile_rcac() - Send abort Agile RCAC to F/W.
* @dfs: Pointer to struct wlan_dfs.
*/
static void dfs_abort_agile_rcac(struct wlan_dfs *dfs)
{
@@ -4376,6 +4352,29 @@ static void dfs_abort_agile_rcac(struct wlan_dfs *dfs)
dfs->dfs_precac_chwidth = CH_WIDTH_INVALID;
dfs->dfs_soc_obj->cur_agile_dfs_index = DFS_PSOC_NO_IDX;
}
#else
static inline void dfs_abort_agile_rcac(struct wlan_dfs *dfs)
{
}
#endif
/* dfs_abort_agile_precac() - Reset parameters of wlan_dfs and send abort
* to F/W.
* @dfs: Pointer to struct wlan_dfs.
*/
static void dfs_abort_agile_precac(struct wlan_dfs *dfs)
{
struct wlan_objmgr_psoc *psoc;
struct wlan_lmac_if_dfs_tx_ops *dfs_tx_ops;
psoc = wlan_pdev_get_psoc(dfs->dfs_pdev_obj);
dfs_tx_ops = wlan_psoc_get_dfs_txops(psoc);
dfs_agile_precac_cleanup(dfs);
/*Send the abort to F/W as well */
if (dfs_tx_ops && dfs_tx_ops->dfs_ocac_abort_cmd)
dfs_tx_ops->dfs_ocac_abort_cmd(dfs->dfs_pdev_obj);
}
/**
* dfs_agile_state_init_entry() - Entry API for INIT state
@@ -4405,6 +4404,40 @@ static void dfs_agile_state_init_exit(void *ctx)
/* NO OPS */
}
/**
* dfs_init_agile_start_evt_handler() - Init state start event handler.
* @dfs: Instance of wlan_dfs structure.
* @dfs_soc: DFS SoC private object
*
* Return : True if PreCAC/RCAC chan is found.
*/
static bool dfs_init_agile_start_evt_handler(struct wlan_dfs *dfs,
struct dfs_soc_priv_obj *dfs_soc)
{
bool is_chan_found = false;
/*For RCAC */
if (dfs_is_agile_rcac_enabled(dfs)) {
/* Check if feature is enabled for this DFS and if RCAC channel
* is valid, if those are true, send appropriate WMIs to FW
* and only then transition to the state as follows.
*/
dfs_prepare_agile_rcac_channel(dfs, &is_chan_found);
}
/*For PreCAC */
else if (dfs_is_agile_precac_enabled(dfs)) {
dfs_soc->dfs_priv[dfs->dfs_psoc_idx].agile_precac_active
= true;
if (!dfs_soc->precac_state_started &&
!dfs_soc->dfs_precac_timer_running) {
dfs_soc->precac_state_started = true;
dfs_prepare_agile_precac_chan(dfs, &is_chan_found);
}
}
return is_chan_found;
}
/**
* dfs_agile_state_init_event() - INIT State event handler
* @ctx: DFS SoC private object
@@ -4425,7 +4458,7 @@ static bool dfs_agile_state_init_event(void *ctx,
struct dfs_soc_priv_obj *dfs_soc = (struct dfs_soc_priv_obj *)ctx;
bool status;
struct wlan_dfs *dfs;
bool is_rcac_chan_available = false;
bool is_chan_found;
if (!event_data)
return false;
@@ -4434,18 +4467,24 @@ static bool dfs_agile_state_init_event(void *ctx,
switch (event) {
case DFS_AGILE_SM_EV_AGILE_START:
/* Check if feature is enabled for this DFS and if RCAC channel
* is valid, if those are true, send appropriate WMIs to FW
* and only then transition to the state as follows.
*/
if (dfs_soc->cur_agile_dfs_index != DFS_PSOC_NO_IDX)
return true;
dfs_prepare_agile_rcac_channel(dfs, &is_rcac_chan_available);
if (is_rcac_chan_available) {
is_chan_found = dfs_init_agile_start_evt_handler(dfs,
dfs_soc);
if (is_chan_found) {
dfs_soc->cur_agile_dfs_index = dfs->dfs_psoc_idx;
dfs_agile_sm_transition_to(dfs_soc, DFS_AGILE_S_RUNNING);
} else {
/*
* This happens when there is no preCAC chan
* in any of the radios
*/
dfs_agile_precac_cleanup(dfs);
/* Cleanup and wait */
}
status = true;
break;
default:
@@ -4471,8 +4510,12 @@ static void dfs_agile_state_running_entry(void *ctx)
dfs_soc->dfs_priv[dfs_soc->cur_agile_dfs_index].dfs;
dfs_agile_set_curr_state(dfs_soc, DFS_AGILE_S_RUNNING);
dfs_start_agile_rcac_timer(dfs);
dfs_start_agile_engine(dfs);
/* RCAC */
if (dfs_is_agile_rcac_enabled(dfs)) {
dfs_start_agile_rcac_timer(dfs);
dfs_start_agile_engine(dfs);
}
}
/**
@@ -4508,6 +4551,7 @@ static bool dfs_agile_state_running_event(void *ctx,
struct dfs_soc_priv_obj *dfs_soc = (struct dfs_soc_priv_obj *)ctx;
bool status;
struct wlan_dfs *dfs;
bool is_cac_done_on_des_chan;
if (!event_data)
return false;
@@ -4530,21 +4574,48 @@ static bool dfs_agile_state_running_event(void *ctx,
* channel not found and stay in that state.
* Abort the existing RCAC and restart from INIT state.
*/
dfs_abort_agile_rcac(dfs);
if (dfs_is_agile_rcac_enabled(dfs))
dfs_abort_agile_rcac(dfs);
else if (dfs_is_agile_precac_enabled(dfs))
dfs_abort_agile_precac(dfs);
dfs_agile_sm_transition_to(dfs_soc, DFS_AGILE_S_INIT);
dfs_agile_sm_deliver_event(dfs_soc,
DFS_AGILE_SM_EV_AGILE_START,
event_data_len,
event_data);
DFS_AGILE_SM_EV_AGILE_START,
event_data_len,
event_data);
status = true;
break;
case DFS_AGILE_SM_EV_AGILE_STOP:
dfs_abort_agile_rcac(dfs);
if (dfs_is_agile_rcac_enabled(dfs))
dfs_abort_agile_rcac(dfs);
else if (dfs_is_agile_precac_enabled(dfs))
dfs_abort_agile_precac(dfs);
dfs_agile_sm_transition_to(dfs_soc, DFS_AGILE_S_INIT);
status = true;
break;
case DFS_AGILE_SM_EV_AGILE_DONE:
dfs_agile_sm_transition_to(dfs_soc, DFS_AGILE_S_COMPLETE);
if (dfs_is_agile_precac_enabled(dfs)) {
if (dfs_soc->ocac_status == OCAC_SUCCESS) {
dfs_soc->ocac_status = OCAC_RESET;
dfs_mark_adfs_chan_as_cac_done(dfs);
}
dfs_agile_sm_transition_to(dfs_soc, DFS_AGILE_S_INIT);
dfs_agile_precac_cleanup(dfs);
is_cac_done_on_des_chan =
dfs_precac_check_home_chan_change(dfs);
if (!is_cac_done_on_des_chan) {
dfs_agile_sm_deliver_event(dfs_soc,
DFS_AGILE_SM_EV_AGILE_START,
event_data_len,
event_data);
}
} else if (dfs_is_agile_rcac_enabled(dfs)) {
dfs_agile_sm_transition_to(dfs_soc,
DFS_AGILE_S_COMPLETE);
}
status = true;
default:
status = false;
@@ -4737,9 +4808,9 @@ static void dfs_agile_sm_print_state_event(struct dfs_soc_priv_obj *dfs_soc_obj,
}
QDF_STATUS dfs_agile_sm_deliver_evt(struct dfs_soc_priv_obj *dfs_soc_obj,
enum dfs_agile_sm_evt event,
uint16_t event_data_len,
void *event_data)
enum dfs_agile_sm_evt event,
uint16_t event_data_len,
void *event_data)
{
enum dfs_agile_sm_state old_state, new_state;
QDF_STATUS status;
@@ -4794,6 +4865,7 @@ QDF_STATUS dfs_agile_sm_destroy(struct dfs_soc_priv_obj *dfs_soc_obj)
return QDF_STATUS_SUCCESS;
}
#ifdef QCA_SUPPORT_ADFS_RCAC
QDF_STATUS dfs_set_rcac_enable(struct wlan_dfs *dfs, bool rcac_en)
{
if (rcac_en == dfs->dfs_agile_rcac_ucfg) {
@@ -4904,3 +4976,4 @@ void dfs_prepare_agile_rcac_channel(struct wlan_dfs *dfs,
rcac_ch_freq);
}
#endif
#endif