qcacld-3.0: Handle DFS channel radar history get vendor command
Add support for QCA_NL80211_VENDOR_SUBCMD_GET_RADAR_HISTORY vendor command. This command will return the current NOL list in driver and the last Radar detection result in previous SAP active state (includes CAC state). Change-Id: I719630c39b89c1813ca05c4356dce627d72d82e2 CRs-Fixed: 2966501
This commit is contained in:

committed by
Madan Koyyalamudi

parent
ed537c76da
commit
3ad4f9d78b
@@ -615,6 +615,35 @@ typedef struct sSapDfsInfo {
|
||||
uint16_t reduced_beacon_interval;
|
||||
} tSapDfsInfo;
|
||||
|
||||
/* MAX number of CAC channels to be recorded */
|
||||
#define MAX_NUM_OF_CAC_HISTORY 8
|
||||
|
||||
/**
|
||||
* struct prev_cac_result - previous cac result
|
||||
* @ap_start_time: ap start timestamp
|
||||
* @ap_end_time: ap stop or cac end timestamp
|
||||
* @cac_complete: cac complete without found radar event
|
||||
* @cac_ch_param: ap channel parameters
|
||||
*/
|
||||
struct prev_cac_result {
|
||||
uint64_t ap_start_time;
|
||||
uint64_t ap_end_time;
|
||||
bool cac_complete;
|
||||
struct ch_params cac_ch_param;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dfs_radar_history - radar found history element
|
||||
* @time: timestamp in us from system boot
|
||||
* @radar_found: radar found or not
|
||||
* @ch_freq: channel frequency in Mhz
|
||||
*/
|
||||
struct dfs_radar_history {
|
||||
uint64_t time;
|
||||
bool radar_found;
|
||||
uint16_t ch_freq;
|
||||
};
|
||||
|
||||
#ifdef DCS_INTERFERENCE_DETECTION
|
||||
/**
|
||||
* struct sap_dcs_info - record sap dcs information.
|
||||
@@ -1546,6 +1575,24 @@ uint32_t wlansap_get_safe_channel_from_pcl_for_sap(struct sap_context *sap_ctx);
|
||||
qdf_freq_t wlansap_get_chan_band_restrict(struct sap_context *sap_ctx,
|
||||
enum sap_csa_reason_code *csa_reason);
|
||||
|
||||
#ifdef FEATURE_RADAR_HISTORY
|
||||
/**
|
||||
* wlansap_query_radar_history() - get radar history info
|
||||
* @mac_handle: mac context
|
||||
* @radar_history: radar history buffer to be returned
|
||||
* @count: total history count
|
||||
*
|
||||
* The API will return the dfs nol list(Radar found history) and
|
||||
* CAC history (no Radar found).
|
||||
*
|
||||
* Return - QDF_STATUS
|
||||
*/
|
||||
QDF_STATUS
|
||||
wlansap_query_radar_history(mac_handle_t mac_handle,
|
||||
struct dfs_radar_history **radar_history,
|
||||
uint32_t *count);
|
||||
#endif
|
||||
|
||||
#ifdef DCS_INTERFERENCE_DETECTION
|
||||
/**
|
||||
* wlansap_dcs_set_vdev_wlan_interference_mitigation() - set wlan
|
||||
|
@@ -1402,6 +1402,245 @@ static bool sap_save_owe_pending_assoc_ind(struct sap_context *sap_ctx,
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef FEATURE_RADAR_HISTORY
|
||||
/* Last cac result */
|
||||
static struct prev_cac_result prev_cac_history;
|
||||
|
||||
/**
|
||||
* sap_update_cac_history() - record SAP Radar found result in last
|
||||
* "active" or CAC period
|
||||
* @mac_ctx: mac context
|
||||
* @sap_ctx: sap context
|
||||
* @event_id: sap event
|
||||
*
|
||||
* The function is to save the dfs channel information
|
||||
* If SAP has been "active" or "CAC" on DFS channel for 60s and
|
||||
* no found radar event.
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
static void
|
||||
sap_update_cac_history(struct mac_context *mac_ctx,
|
||||
struct sap_context *sap_ctx,
|
||||
eSapHddEvent event_id)
|
||||
{
|
||||
struct prev_cac_result *cac_result = &sap_ctx->cac_result;
|
||||
|
||||
switch (event_id) {
|
||||
case eSAP_START_BSS_EVENT:
|
||||
case eSAP_CHANNEL_CHANGE_RESP:
|
||||
case eSAP_DFS_CAC_START:
|
||||
if (sap_operating_on_dfs(mac_ctx, sap_ctx)) {
|
||||
qdf_mem_zero(cac_result,
|
||||
sizeof(struct prev_cac_result));
|
||||
if (!sap_ctx->ch_params.mhz_freq_seg0) {
|
||||
sap_debug("invalid seq0");
|
||||
return;
|
||||
}
|
||||
cac_result->ap_start_time =
|
||||
qdf_get_monotonic_boottime();
|
||||
cac_result->cac_ch_param = sap_ctx->ch_params;
|
||||
sap_debug("ap start(CAC) (%d, %d) bw %d",
|
||||
cac_result->cac_ch_param.mhz_freq_seg0,
|
||||
cac_result->cac_ch_param.mhz_freq_seg1,
|
||||
cac_result->cac_ch_param.ch_width);
|
||||
}
|
||||
break;
|
||||
case eSAP_DFS_RADAR_DETECT:
|
||||
qdf_mem_zero(cac_result,
|
||||
sizeof(struct prev_cac_result));
|
||||
break;
|
||||
case eSAP_DFS_CAC_END:
|
||||
case eSAP_STOP_BSS_EVENT:
|
||||
if (cac_result->ap_start_time) {
|
||||
uint64_t diff_ms;
|
||||
|
||||
cac_result->ap_end_time =
|
||||
qdf_get_monotonic_boottime();
|
||||
diff_ms = qdf_do_div(cac_result->ap_end_time -
|
||||
cac_result->ap_start_time, 1000);
|
||||
if (diff_ms < DEFAULT_CAC_TIMEOUT - 5000) {
|
||||
if (event_id == eSAP_STOP_BSS_EVENT)
|
||||
qdf_mem_zero(
|
||||
cac_result,
|
||||
sizeof(struct prev_cac_result));
|
||||
sap_debug("ap cac dur %llu ms", diff_ms);
|
||||
break;
|
||||
}
|
||||
cac_result->cac_complete = true;
|
||||
qdf_mem_copy(&prev_cac_history, cac_result,
|
||||
sizeof(struct prev_cac_result));
|
||||
sap_debug("ap cac saved %llu ms %llu (%d, %d) bw %d",
|
||||
diff_ms,
|
||||
cac_result->ap_end_time,
|
||||
cac_result->cac_ch_param.mhz_freq_seg0,
|
||||
cac_result->cac_ch_param.mhz_freq_seg1,
|
||||
cac_result->cac_ch_param.ch_width);
|
||||
if (event_id == eSAP_STOP_BSS_EVENT)
|
||||
qdf_mem_zero(cac_result,
|
||||
sizeof(struct prev_cac_result));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* find_ch_freq_in_radar_hist() - check channel frequency existing
|
||||
* in radar history buffer
|
||||
* @radar_result: radar history buffer
|
||||
* @count: radar history element number
|
||||
* @ch_freq: channel frequency
|
||||
*
|
||||
* Return: bool
|
||||
*/
|
||||
static
|
||||
bool find_ch_freq_in_radar_hist(struct dfs_radar_history *radar_result,
|
||||
uint32_t count, uint16_t ch_freq)
|
||||
{
|
||||
while (count) {
|
||||
if (radar_result->ch_freq == ch_freq)
|
||||
return true;
|
||||
radar_result++;
|
||||
count--;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* sap_append_cac_history() - Add CAC history to list
|
||||
* @radar_result: radar history buffer
|
||||
* @idx: current radar history element number
|
||||
* @max_elems: max elements nummber of radar history buffer.
|
||||
*
|
||||
* This function is to add the CAC history to radar history list.
|
||||
*
|
||||
* Return: void
|
||||
*/
|
||||
static
|
||||
void sap_append_cac_history(struct mac_context *mac_ctx,
|
||||
struct dfs_radar_history *radar_result,
|
||||
uint32_t *idx, uint32_t max_elems)
|
||||
{
|
||||
struct prev_cac_result *cac_result = &prev_cac_history;
|
||||
struct ch_params ch_param = cac_result->cac_ch_param;
|
||||
uint32_t count = *idx;
|
||||
|
||||
if (!cac_result->cac_complete || !cac_result->ap_end_time) {
|
||||
sap_debug("cac hist empty");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ch_param.ch_width <= CH_WIDTH_20MHZ) {
|
||||
if (wlan_reg_is_dfs_for_freq(mac_ctx->pdev,
|
||||
ch_param.mhz_freq_seg0) &&
|
||||
!find_ch_freq_in_radar_hist(radar_result, count,
|
||||
ch_param.mhz_freq_seg0) &&
|
||||
*idx < max_elems) {
|
||||
radar_result[*idx].ch_freq = ch_param.mhz_freq_seg0;
|
||||
radar_result[*idx].time = cac_result->ap_end_time;
|
||||
radar_result[*idx].radar_found = false;
|
||||
sap_debug("radar hist[%d] freq %d time %llu no radar",
|
||||
*idx, ch_param.mhz_freq_seg0,
|
||||
cac_result->ap_end_time);
|
||||
(*idx)++;
|
||||
}
|
||||
} else {
|
||||
uint16_t chan_cfreq;
|
||||
enum channel_state state;
|
||||
const struct bonded_channel_freq *bonded_chan_ptr = NULL;
|
||||
|
||||
state = wlan_reg_get_5g_bonded_channel_and_state_for_freq
|
||||
(mac_ctx->pdev, ch_param.mhz_freq_seg0,
|
||||
ch_param.ch_width, &bonded_chan_ptr);
|
||||
if (!bonded_chan_ptr || state == CHANNEL_STATE_INVALID) {
|
||||
sap_debug("invalid freq %d", ch_param.mhz_freq_seg0);
|
||||
return;
|
||||
}
|
||||
|
||||
chan_cfreq = bonded_chan_ptr->start_freq;
|
||||
while (chan_cfreq <= bonded_chan_ptr->end_freq) {
|
||||
state = wlan_reg_get_channel_state_for_freq(
|
||||
mac_ctx->pdev, chan_cfreq);
|
||||
if (state == CHANNEL_STATE_INVALID) {
|
||||
sap_debug("invalid ch freq %d",
|
||||
chan_cfreq);
|
||||
chan_cfreq = chan_cfreq + 20;
|
||||
continue;
|
||||
}
|
||||
if (wlan_reg_is_dfs_for_freq(mac_ctx->pdev,
|
||||
chan_cfreq) &&
|
||||
!find_ch_freq_in_radar_hist(radar_result, count,
|
||||
chan_cfreq) &&
|
||||
*idx < max_elems) {
|
||||
radar_result[*idx].ch_freq = chan_cfreq;
|
||||
radar_result[*idx].time =
|
||||
cac_result->ap_end_time;
|
||||
radar_result[*idx].radar_found = false;
|
||||
sap_debug("radar hist[%d] freq %d time %llu no radar",
|
||||
*idx, chan_cfreq,
|
||||
cac_result->ap_end_time);
|
||||
(*idx)++;
|
||||
}
|
||||
chan_cfreq = chan_cfreq + 20;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QDF_STATUS
|
||||
wlansap_query_radar_history(mac_handle_t mac_handle,
|
||||
struct dfs_radar_history **radar_history,
|
||||
uint32_t *count)
|
||||
{
|
||||
struct mac_context *mac_ctx = MAC_CONTEXT(mac_handle);
|
||||
struct dfsreq_nolinfo *nol_info;
|
||||
uint32_t i;
|
||||
uint32_t hist_count;
|
||||
struct dfs_radar_history *radar_result;
|
||||
|
||||
nol_info = qdf_mem_malloc(sizeof(struct dfsreq_nolinfo));
|
||||
if (!nol_info)
|
||||
return QDF_STATUS_E_NOMEM;
|
||||
|
||||
ucfg_dfs_getnol(mac_ctx->pdev, nol_info);
|
||||
|
||||
hist_count = nol_info->dfs_ch_nchans + MAX_NUM_OF_CAC_HISTORY;
|
||||
radar_result = qdf_mem_malloc(sizeof(struct dfs_radar_history) *
|
||||
hist_count);
|
||||
if (!radar_result) {
|
||||
qdf_mem_free(nol_info);
|
||||
return QDF_STATUS_E_NOMEM;
|
||||
}
|
||||
|
||||
for (i = 0; i < nol_info->dfs_ch_nchans && i < DFS_CHAN_MAX; i++) {
|
||||
radar_result[i].ch_freq = nol_info->dfs_nol[i].nol_freq;
|
||||
radar_result[i].time = nol_info->dfs_nol[i].nol_start_us;
|
||||
radar_result[i].radar_found = true;
|
||||
sap_debug("radar hist[%d] freq %d time %llu radar",
|
||||
i, nol_info->dfs_nol[i].nol_freq,
|
||||
nol_info->dfs_nol[i].nol_start_us);
|
||||
}
|
||||
|
||||
sap_append_cac_history(mac_ctx, radar_result, &i, hist_count);
|
||||
sap_debug("hist count %d cur %llu", i, qdf_get_monotonic_boottime());
|
||||
|
||||
*radar_history = radar_result;
|
||||
*count = i;
|
||||
qdf_mem_free(nol_info);
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
#else
|
||||
static inline void
|
||||
sap_update_cac_history(struct mac_context *mac_ctx,
|
||||
struct sap_context *sap_ctx,
|
||||
eSapHddEvent event_id)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* sap_signal_hdd_event() - send event notification
|
||||
* @sap_ctx: Sap Context
|
||||
@@ -1506,6 +1745,9 @@ QDF_STATUS sap_signal_hdd_event(struct sap_context *sap_ctx,
|
||||
|
||||
bss_complete->operating_chan_freq = sap_ctx->chan_freq;
|
||||
bss_complete->ch_width = sap_ctx->ch_params.ch_width;
|
||||
if (QDF_IS_STATUS_SUCCESS(bss_complete->status))
|
||||
sap_update_cac_history(mac_ctx, sap_ctx,
|
||||
sap_hddevent);
|
||||
break;
|
||||
case eSAP_DFS_CAC_START:
|
||||
case eSAP_DFS_CAC_INTERRUPTED:
|
||||
@@ -1517,6 +1759,8 @@ QDF_STATUS sap_signal_hdd_event(struct sap_context *sap_ctx,
|
||||
sap_ap_event->sapHddEventCode = sap_hddevent;
|
||||
sap_ap_event->sapevt.sapStopBssCompleteEvent.status =
|
||||
(eSapStatus) context;
|
||||
sap_update_cac_history(mac_ctx, sap_ctx,
|
||||
sap_hddevent);
|
||||
break;
|
||||
case eSAP_ACS_SCAN_SUCCESS_EVENT:
|
||||
sap_handle_acs_scan_event(sap_ctx, sap_ap_event,
|
||||
@@ -1820,6 +2064,8 @@ QDF_STATUS sap_signal_hdd_event(struct sap_context *sap_ctx,
|
||||
sap_ctx->csr_roamProfile.ch_params.mhz_freq_seg0;
|
||||
acs_selected->vht_seg1_center_ch_freq =
|
||||
sap_ctx->csr_roamProfile.ch_params.mhz_freq_seg1;
|
||||
sap_update_cac_history(mac_ctx, sap_ctx,
|
||||
sap_hddevent);
|
||||
sap_debug("SAP event callback event = %s",
|
||||
"eSAP_CHANNEL_CHANGE_RESP");
|
||||
break;
|
||||
|
@@ -193,7 +193,9 @@ struct sap_context {
|
||||
bool isCacEndNotified;
|
||||
bool isCacStartNotified;
|
||||
bool is_sap_ready_for_chnl_chng;
|
||||
|
||||
#ifdef FEATURE_RADAR_HISTORY
|
||||
struct prev_cac_result cac_result;
|
||||
#endif
|
||||
#ifdef FEATURE_AP_MCC_CH_AVOIDANCE
|
||||
/*
|
||||
* In a setup having two MDM both operating in AP+AP MCC scenario
|
||||
|
Reference in New Issue
Block a user