diff --git a/umac/dfs/core/src/dfs.h b/umac/dfs/core/src/dfs.h index c11224e4ce..a63f69f72a 100644 --- a/umac/dfs/core/src/dfs.h +++ b/umac/dfs/core/src/dfs.h @@ -1011,6 +1011,23 @@ struct wlan_dfs { qdf_spinlock_t dfs_nol_lock; }; +/** + * struct dfs_soc_priv_obj - dfs private data + * @psoc: pointer to PSOC object information + * @pdev: pointer to PDEV object information + * @dfs_is_phyerr_filter_offload: For some chip like Rome indicates too many + * phyerr packets in a short time, which causes + * OS hang. If this feild is configured as true, + * FW will do the pre-check, filter out some + * kinds of invalid phyerrors and indicate + * radar detection related information to host. + */ +struct dfs_soc_priv_obj { + struct wlan_objmgr_psoc *psoc; + struct wlan_objmgr_pdev *pdev; + bool dfs_is_phyerr_filter_offload; +}; + /** * enum DFS debug - This should match the table from if_ath.c. * @WLAN_DEBUG_DFS: Minimal DFS debug. @@ -1590,6 +1607,18 @@ void dfs_process_phyerr(struct wlan_dfs *dfs, uint32_t r_rs_tstamp, uint64_t r_fulltsf); +#ifdef QCA_MCL_DFS_SUPPORT +/** + * dfs_process_phyerr_filter_offload() - Process radar event. + * @dfs: Pointer to wlan_dfs structure. + * @wlan_radar_event: Pointer to radar_event_info structure. + * + * Return: None + */ +void dfs_process_phyerr_filter_offload(struct wlan_dfs *dfs, + struct radar_event_info *wlan_radar_event); +#endif + /** * dfs_is_precac_timer_running() - Check whether precac timer is running. * @dfs: Pointer to wlan_dfs structure. @@ -2118,4 +2147,12 @@ wlan_psoc_get_dfs_txops(struct wlan_objmgr_psoc *psoc); * @dfs: Pointer to wlan_dfs structure. */ void dfs_nol_free_list(struct wlan_dfs *dfs); + +/** + * dfs_set_phyerr_filter_offload - config phyerr filter offload. + * @dfs: Pointer to wlan_dfs structure. + * + * Return: None + */ +void dfs_set_phyerr_filter_offload(struct wlan_dfs *dfs); #endif /* _DFS_H_ */ diff --git a/umac/dfs/core/src/filtering/dfs_process_phyerr.c b/umac/dfs/core/src/filtering/dfs_process_phyerr.c index b0aa9fd482..6856014445 100644 --- a/umac/dfs/core/src/filtering/dfs_process_phyerr.c +++ b/umac/dfs/core/src/filtering/dfs_process_phyerr.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2018 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 @@ -845,3 +845,139 @@ void dfs_process_phyerr(struct wlan_dfs *dfs, void *buf, uint16_t datalen, #undef PRI_CH_RADAR_FOUND #undef EXT_CH_RADAR_EARLY_FOUND } + +#ifdef QCA_MCL_DFS_SUPPORT +void dfs_process_phyerr_filter_offload(struct wlan_dfs *dfs, + struct radar_event_info *wlan_radar_event) +{ + struct dfs_event *event; + int empty; + int do_check_chirp = 0; + int is_hw_chirp = 0; + int is_sw_chirp = 0; + int is_pri = 0; + + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); + return; + } + + if (dfs->dfs_ignore_dfs) { + dfs_debug(dfs, WLAN_DEBUG_DFS1, "ignoring dfs"); + return; + } + + if (!(dfs->dfs_proc_phyerr & DFS_RADAR_EN)) { + dfs_debug(dfs, WLAN_DEBUG_DFS1, + "DFS_RADAR_EN not set in dfs->dfs_proc_phyerr"); + return; + } + + if (WLAN_IS_CHAN_RADAR(dfs->dfs_curchan)) { + dfs_debug(dfs, WLAN_DEBUG_DFS1, + "Radar already found in the channel, do not queue radar data"); + return; + } + + dfs->wlan_dfs_stats.total_phy_errors++; + if (dfs->dfs_caps.wlan_chip_is_bb_tlv) { + do_check_chirp = 1; + is_pri = 1; + is_hw_chirp = wlan_radar_event->pulse_is_chirp; + + if ((uint32_t) dfs->dfs_phyerr_freq_min > + wlan_radar_event->pulse_center_freq) { + dfs->dfs_phyerr_freq_min = + (int)wlan_radar_event->pulse_center_freq; + } + + if (dfs->dfs_phyerr_freq_max < + (int)wlan_radar_event->pulse_center_freq) { + dfs->dfs_phyerr_freq_max = + (int)wlan_radar_event->pulse_center_freq; + } + } + + /* + * Now, add the parsed, checked and filtered + * radar phyerror event radar pulse event list. + * This event will then be processed by + * dfs_radar_processevent() to see if the pattern + * of pulses in radar pulse list match any radar + * singnature in the current regulatory domain. + */ + + WLAN_DFSEVENTQ_LOCK(dfs); + empty = STAILQ_EMPTY(&(dfs->dfs_eventq)); + WLAN_DFSEVENTQ_UNLOCK(dfs); + if (empty) + return; + /* + * Add the event to the list, if there's space. + */ + WLAN_DFSEVENTQ_LOCK(dfs); + event = STAILQ_FIRST(&(dfs->dfs_eventq)); + if (!event) { + WLAN_DFSEVENTQ_UNLOCK(dfs); + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, + "%s: No more space left for queuing DFS Phyerror events", + __func__); + return; + } + STAILQ_REMOVE_HEAD(&(dfs->dfs_eventq), re_list); + WLAN_DFSEVENTQ_UNLOCK(dfs); + dfs->dfs_phyerr_queued_count++; + dfs->dfs_phyerr_w53_counter++; + event->re_dur = (uint8_t) wlan_radar_event->pulse_duration; + event->re_rssi = wlan_radar_event->rssi; + event->re_ts = wlan_radar_event->pulse_detect_ts & DFS_TSMASK; + event->re_full_ts = (((uint64_t) wlan_radar_event->upload_fullts_high) + << 32) | wlan_radar_event->upload_fullts_low; + + /* + * Index of peak magnitude + */ + event->re_sidx = wlan_radar_event->peak_sidx; + event->re_delta_diff = 0; + event->re_delta_peak = 0; + event->re_flags = 0; + + /* + * Handle chirp flags. + */ + if (do_check_chirp) { + event->re_flags |= DFS_EVENT_CHECKCHIRP; + if (is_hw_chirp) + event->re_flags |= DFS_EVENT_HW_CHIRP; + if (is_sw_chirp) + event->re_flags |= DFS_EVENT_SW_CHIRP; + } + /* + * Correctly set which channel is being reported on + */ + if (is_pri) { + event->re_chanindex = (uint8_t) dfs->dfs_curchan_radindex; + } else { + if (dfs->dfs_extchan_radindex == -1) + dfs_debug(dfs, WLAN_DEBUG_DFS1, + "%s phyerr on ext channel", __func__); + event->re_chanindex = (uint8_t) dfs->dfs_extchan_radindex; + dfs_debug(dfs, WLAN_DEBUG_DFS1, + "%s:New extension channel event is added to queue", + __func__); + } + + WLAN_DFSQ_LOCK(dfs); + + STAILQ_INSERT_TAIL(&(dfs->dfs_radarq), event, re_list); + + empty = STAILQ_EMPTY(&dfs->dfs_radarq); + + WLAN_DFSQ_UNLOCK(dfs); + + if (!empty && !dfs->wlan_radar_tasksched) { + dfs->wlan_radar_tasksched = 1; + qdf_timer_mod(&dfs->wlan_dfs_task_timer, 0); + } +} +#endif diff --git a/umac/dfs/core/src/misc/dfs.c b/umac/dfs/core/src/misc/dfs.c index 2332eae7e8..fc95116637 100644 --- a/umac/dfs/core/src/misc/dfs.c +++ b/umac/dfs/core/src/misc/dfs.c @@ -276,6 +276,7 @@ int dfs_main_attach(struct wlan_dfs *dfs) dfs->dfs_phyerr_w53_counter = 0; dfs->dfs_pri_multiplier = 2; dfs_get_radars(dfs); + dfs_set_phyerr_filter_offload(dfs); return 0; @@ -1079,3 +1080,14 @@ void dfs_update_cur_chan_flags(struct wlan_dfs *dfs, dfs->dfs_curchan->dfs_ch_flags = flags; dfs->dfs_curchan->dfs_ch_flagext = flagext; } + +#ifdef QCA_MCL_DFS_SUPPORT +void dfs_set_phyerr_filter_offload(struct wlan_dfs *dfs) +{ + tgt_dfs_set_phyerr_filter_offload(dfs->dfs_pdev_obj); +} +#else +void dfs_set_phyerr_filter_offload(struct wlan_dfs *dfs) +{ +} +#endif diff --git a/umac/dfs/dispatcher/inc/wlan_dfs_public_struct.h b/umac/dfs/dispatcher/inc/wlan_dfs_public_struct.h index bfc7bb5837..bd22e6a3fd 100644 --- a/umac/dfs/dispatcher/inc/wlan_dfs_public_struct.h +++ b/umac/dfs/dispatcher/inc/wlan_dfs_public_struct.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018 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 @@ -64,4 +64,38 @@ struct dfs_acs_info { uint8_t start_ch; uint8_t end_ch; }; + +/** + * struct radar_event_info - radar event info. + * @pulse_is_chirp: flag to indicate if this pulse is chirp. + * @pulse_center_freq: the center frequency of the radar pulse detected, KHz. + * @pulse_duration: the duaration of the pulse in us. + * @rssi: RSSI recorded in the ppdu. + * @pulse_detect_ts: timestamp indicates the time when DFS pulse is detected. + * @upload_fullts_low: low 32 tsf timestamp get from MAC tsf timer indicates + * the time that the radar event uploading to host. + * @upload_fullts_high: high 32 tsf timestamp get from MAC tsf timer indicates + * the time that the radar event uploading to host. + * @peak_sidx: index of peak magnitude bin (signed) + * @pdev_id: pdev_id for identifying the MAC. + */ +struct radar_event_info { + uint8_t pulse_is_chirp; + uint32_t pulse_center_freq; + uint32_t pulse_duration; + uint8_t rssi; + uint32_t pulse_detect_ts; + uint32_t upload_fullts_low; + uint32_t upload_fullts_high; + int32_t peak_sidx; + uint8_t pdev_id; +}; + +/** + * struct dfs_user_config - user configuration required for for DFS. + * @dfs_is_phyerr_filter_offload: flag to indicate DFS phyerr filtering offload. + */ +struct dfs_user_config { + bool dfs_is_phyerr_filter_offload; +}; #endif diff --git a/umac/dfs/dispatcher/inc/wlan_dfs_tgt_api.h b/umac/dfs/dispatcher/inc/wlan_dfs_tgt_api.h index e7a08133ea..4a6fdc54a6 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-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -116,6 +116,28 @@ QDF_STATUS tgt_dfs_process_phyerr(struct wlan_objmgr_pdev *pdev, uint32_t r_rs_tstamp, uint64_t r_fulltsf); +/** + * tgt_dfs_process_phyerr_filter_offload() - Process radar event. + * Wrapper function for dfs_process_phyerr_filter_offload(). This function + * called from outside of DFS component. + * @pdev: Pointer to DFS pdev object. + * @wlan_radar_event: pointer to radar_event_info. + * + * Return: QDF_STATUS + */ +QDF_STATUS tgt_dfs_process_phyerr_filter_offload(struct wlan_objmgr_pdev *pdev, + struct radar_event_info *wlan_radar_event); + +/** + * tgt_dfs_is_phyerr_filter_offload() - Is phyerr filter offload. + * @pdev: Pointer to DFS pdev object. + * @is_phyerr_filter_offload: Pointer to is_phyerr_filter_offload. + * + * Return: QDF_STATUS + */ +QDF_STATUS tgt_dfs_is_phyerr_filter_offload(struct wlan_objmgr_pdev *pdev, + bool *is_phyerr_filter_offload); + /** * tgt_dfs_destroy_object() - Destroys the DFS object. * @pdev: Pointer to DFS pdev object. @@ -241,4 +263,13 @@ QDF_STATUS tgt_dfs_stop(struct wlan_objmgr_pdev *pdev); QDF_STATUS tgt_dfs_process_emulate_bang_radar_cmd(struct wlan_objmgr_pdev *pdev, struct dfs_emulate_bang_radar_test_cmd *dfs_unit_test); +#ifdef QCA_MCL_DFS_SUPPORT +/** + * tgt_dfs_set_phyerr_filter_offload() - config phyerr filter offload + * @pdev: Pointer to DFS pdev object. + * + * Return: QDF_STATUS + */ +QDF_STATUS tgt_dfs_set_phyerr_filter_offload(struct wlan_objmgr_pdev *pdev); +#endif #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 1a745b9451..cd41d357fe 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-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -232,4 +232,15 @@ QDF_STATUS ucfg_dfs_set_precac_enable(struct wlan_objmgr_pdev *pdev, */ QDF_STATUS ucfg_dfs_get_precac_enable(struct wlan_objmgr_pdev *pdev, int *buff); +#ifdef QCA_MCL_DFS_SUPPORT +/** + * ucfg_dfs_update_config() - Update DFS user config. + * @psoc: Pointer to psoc. + * @req: DFS user config. + * + * Return: QDF_STATUS + */ +QDF_STATUS ucfg_dfs_update_config(struct wlan_objmgr_psoc *psoc, + struct dfs_user_config *req); +#endif #endif /* _WLAN_DFS_UCFG_API_H_ */ 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 c6e714e488..1ea891ac07 100644 --- a/umac/dfs/dispatcher/src/wlan_dfs_init_deinit_api.c +++ b/umac/dfs/dispatcher/src/wlan_dfs_init_deinit_api.c @@ -94,49 +94,192 @@ void register_dfs_callbacks(void) } #endif +/** + * dfs_psoc_obj_create_notification() - dfs psoc create notification handler + * @psoc: psoc object + * @arg_list: Argument list + * + * Return: QDF_STATUS + */ +static QDF_STATUS dfs_psoc_obj_create_notification(struct wlan_objmgr_psoc *psoc, + void *arg_list) +{ + QDF_STATUS status; + struct dfs_soc_priv_obj *dfs_soc_obj; + + dfs_soc_obj = qdf_mem_malloc(sizeof(*dfs_soc_obj)); + if (!dfs_soc_obj) { + dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, + "Failed to allocate memory for dfs object"); + return QDF_STATUS_E_NOMEM; + } + + dfs_soc_obj->psoc = psoc; + + status = wlan_objmgr_psoc_component_obj_attach(psoc, + WLAN_UMAC_COMP_DFS, + (void *)dfs_soc_obj, + QDF_STATUS_SUCCESS); + + if (QDF_IS_STATUS_ERROR(status)) { + dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, + "Failed to attach psoc dfs component"); + qdf_mem_free(dfs_soc_obj); + return status; + } + + dfs_debug(NULL, WLAN_DEBUG_DFS1, + "DFS obj attach to psoc successfully"); + + return status; +} + +/** + * dfs_psoc_obj_destroy_notification() - dfs psoc destroy notification handler + * @psoc: psoc object + * @arg_list: Argument list + * + * Return: QDF_STATUS + */ +static QDF_STATUS dfs_psoc_obj_destroy_notification(struct wlan_objmgr_psoc *psoc, + void *arg_list) +{ + QDF_STATUS status; + struct dfs_soc_priv_obj *dfs_soc_obj; + + dfs_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, + WLAN_UMAC_COMP_DFS); + if (!dfs_soc_obj) { + dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, + "Failed to get dfs obj in psoc"); + return QDF_STATUS_E_FAILURE; + } + + status = wlan_objmgr_psoc_component_obj_detach(psoc, + WLAN_UMAC_COMP_DFS, + dfs_soc_obj); + + if (QDF_IS_STATUS_ERROR(status)) + dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, + "Failed to detach psoc dfs component"); + + qdf_mem_free(dfs_soc_obj); + + return status; +} + QDF_STATUS dfs_init(void) { - QDF_STATUS res; + QDF_STATUS status; + + status = wlan_objmgr_register_psoc_create_handler(WLAN_UMAC_COMP_DFS, + dfs_psoc_obj_create_notification, + NULL); + + if (QDF_IS_STATUS_ERROR(status)) { + dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, + "Failed to register psoc create handler for dfs"); + goto err_psoc_create; + } + + status = wlan_objmgr_register_psoc_destroy_handler(WLAN_UMAC_COMP_DFS, + dfs_psoc_obj_destroy_notification, + NULL); + + if (QDF_IS_STATUS_ERROR(status)) { + dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, + "Failed to register psoc delete handler for dfs"); + goto err_psoc_delete; + } register_dfs_callbacks(); - if (wlan_objmgr_register_pdev_create_handler(WLAN_UMAC_COMP_DFS, - wlan_dfs_pdev_obj_create_notification, - NULL) - != QDF_STATUS_SUCCESS) { - return QDF_STATUS_E_FAILURE; - } - if (wlan_objmgr_register_pdev_destroy_handler(WLAN_UMAC_COMP_DFS, - wlan_dfs_pdev_obj_destroy_notification, - NULL) - != QDF_STATUS_SUCCESS) { - return QDF_STATUS_E_FAILURE; + status = wlan_objmgr_register_pdev_create_handler(WLAN_UMAC_COMP_DFS, + wlan_dfs_pdev_obj_create_notification, + NULL); + + if (QDF_IS_STATUS_ERROR(status)) { + dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, + "Failed to register pdev create handler for dfs"); + goto err_pdev_create; } - res = qdf_print_set_category_verbose(qdf_get_pidx(), + status = wlan_objmgr_register_pdev_destroy_handler(WLAN_UMAC_COMP_DFS, + wlan_dfs_pdev_obj_destroy_notification, + NULL); + + if (QDF_IS_STATUS_ERROR(status)) { + dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, + "Failed to register pdev delete handler for dfs"); + goto err_pdev_delete; + } + + status = qdf_print_set_category_verbose(qdf_get_pidx(), QDF_MODULE_ID_DFS, QDF_TRACE_LEVEL_INFO, true); - if (res) { - dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "Failed to set verbose for category"); - return QDF_STATUS_E_FAILURE; + + if (QDF_IS_STATUS_ERROR(status)) { + dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, + "Failed to set verbose for category"); + goto err_category_verbose; } return QDF_STATUS_SUCCESS; + +err_category_verbose: + wlan_objmgr_unregister_pdev_destroy_handler(WLAN_UMAC_COMP_DFS, + wlan_dfs_pdev_obj_destroy_notification, + NULL); +err_pdev_delete: + wlan_objmgr_unregister_pdev_create_handler(WLAN_UMAC_COMP_DFS, + wlan_dfs_pdev_obj_create_notification, + NULL); +err_pdev_create: + wlan_objmgr_unregister_psoc_destroy_handler(WLAN_UMAC_COMP_DFS, + dfs_psoc_obj_destroy_notification, + NULL); +err_psoc_delete: + wlan_objmgr_unregister_psoc_create_handler(WLAN_UMAC_COMP_DFS, + dfs_psoc_obj_create_notification, + NULL); +err_psoc_create: + return status; } QDF_STATUS dfs_deinit(void) { - if (wlan_objmgr_unregister_pdev_create_handler(WLAN_UMAC_COMP_DFS, - wlan_dfs_pdev_obj_create_notification, - NULL) - != QDF_STATUS_SUCCESS) { - return QDF_STATUS_E_FAILURE; - } - if (wlan_objmgr_unregister_pdev_destroy_handler(WLAN_UMAC_COMP_DFS, - wlan_dfs_pdev_obj_destroy_notification, - NULL) - != QDF_STATUS_SUCCESS) { - return QDF_STATUS_E_FAILURE; - } + QDF_STATUS status; + + status = wlan_objmgr_unregister_psoc_create_handler(WLAN_UMAC_COMP_DFS, + dfs_psoc_obj_create_notification, + NULL); + + if (QDF_IS_STATUS_ERROR(status)) + dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, + "Failed to deregister dfs psoc obj create"); + + status = wlan_objmgr_unregister_psoc_destroy_handler(WLAN_UMAC_COMP_DFS, + dfs_psoc_obj_destroy_notification, + NULL); + + if (QDF_IS_STATUS_ERROR(status)) + dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, + "Failed to deregister dfs psoc obj destroy"); + + status = wlan_objmgr_unregister_pdev_create_handler(WLAN_UMAC_COMP_DFS, + wlan_dfs_pdev_obj_create_notification, + NULL); + + if (QDF_IS_STATUS_ERROR(status)) + dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, + "Failed to deregister dfs pdev obj create"); + + status = wlan_objmgr_unregister_pdev_destroy_handler(WLAN_UMAC_COMP_DFS, + wlan_dfs_pdev_obj_destroy_notification, + NULL); + + if (QDF_IS_STATUS_ERROR(status)) + dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, + "Failed to deregister dfs pdev obj destroy"); return QDF_STATUS_SUCCESS; } diff --git a/umac/dfs/dispatcher/src/wlan_dfs_tgt_api.c b/umac/dfs/dispatcher/src/wlan_dfs_tgt_api.c index 75abfad8ab..b4967ef29d 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-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -110,6 +110,68 @@ QDF_STATUS tgt_dfs_process_phyerr(struct wlan_objmgr_pdev *pdev, } EXPORT_SYMBOL(tgt_dfs_process_phyerr); +#ifdef QCA_MCL_DFS_SUPPORT +QDF_STATUS tgt_dfs_process_phyerr_filter_offload(struct wlan_objmgr_pdev *pdev, + struct radar_event_info *wlan_radar_event) +{ + struct wlan_dfs *dfs; + + dfs = global_dfs_to_mlme.pdev_get_comp_private_obj(pdev); + if (!dfs) { + dfs_err(dfs, WLAN_DEBUG_DFS_ALWAYS, "dfs is NULL"); + return QDF_STATUS_E_FAILURE; + } + if (!dfs->dfs_is_offload_enabled) + dfs_process_phyerr_filter_offload(dfs, wlan_radar_event); + else + dfs_info(dfs, WLAN_DEBUG_DFS_ALWAYS, + "Received a pulse from firmware even though the DFS is offloaded" + ); + + return QDF_STATUS_SUCCESS; +} +EXPORT_SYMBOL(tgt_dfs_process_phyerr_filter_offload); + +QDF_STATUS tgt_dfs_is_phyerr_filter_offload(struct wlan_objmgr_pdev *pdev, + bool *is_phyerr_filter_offload) +{ + struct wlan_objmgr_psoc *psoc; + struct dfs_soc_priv_obj *soc_obj; + + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) { + dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "psoc is null"); + return QDF_STATUS_E_FAILURE; + } + + soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, + WLAN_UMAC_COMP_DFS); + if (!soc_obj) { + dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, + "Failed to get dfs psoc component"); + return QDF_STATUS_E_FAILURE; + } + + *is_phyerr_filter_offload = soc_obj->dfs_is_phyerr_filter_offload; + + return QDF_STATUS_SUCCESS; +} +EXPORT_SYMBOL(tgt_dfs_is_phyerr_filter_offload); +#else +QDF_STATUS tgt_dfs_process_phyerr_filter_offload( + struct wlan_objmgr_pdev *pdev, + struct radar_event_info *wlan_radar_event) +{ + return QDF_STATUS_SUCCESS; +} +QDF_STATUS tgt_dfs_is_phyerr_filter_offload( + struct wlan_objmgr_pdev *pdev, + bool *is_phyerr_filter_offload) +{ + return QDF_STATUS_SUCCESS; +} +#endif + QDF_STATUS tgt_dfs_is_precac_timer_running(struct wlan_objmgr_pdev *pdev, bool *is_precac_timer_running) { @@ -313,3 +375,36 @@ QDF_STATUS tgt_dfs_process_emulate_bang_radar_cmd(struct wlan_objmgr_pdev *pdev, return QDF_STATUS_E_FAILURE; } EXPORT_SYMBOL(tgt_dfs_process_emulate_bang_radar_cmd); + +#ifdef QCA_MCL_DFS_SUPPORT +QDF_STATUS tgt_dfs_set_phyerr_filter_offload(struct wlan_objmgr_pdev *pdev) +{ + struct wlan_objmgr_psoc *psoc; + struct wlan_lmac_if_dfs_tx_ops *dfs_tx_ops; + struct dfs_soc_priv_obj *soc_obj; + + psoc = wlan_pdev_get_psoc(pdev); + if (!psoc) { + dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, "psoc is null"); + return QDF_STATUS_E_FAILURE; + } + + soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, + WLAN_UMAC_COMP_DFS); + if (!soc_obj) { + dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, + "Failed to get dfs psoc component"); + return QDF_STATUS_E_FAILURE; + } + dfs_tx_ops = wlan_psoc_get_dfs_txops(psoc); + if (dfs_tx_ops && dfs_tx_ops->dfs_set_phyerr_filter_offload) + return dfs_tx_ops->dfs_set_phyerr_filter_offload(pdev, + soc_obj->dfs_is_phyerr_filter_offload); + else + dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, + "dfs_tx_ops=%pK", dfs_tx_ops); + + return QDF_STATUS_E_FAILURE; +} +EXPORT_SYMBOL(tgt_dfs_set_phyerr_filter_offload); +#endif diff --git a/umac/dfs/dispatcher/src/wlan_dfs_ucfg_api.c b/umac/dfs/dispatcher/src/wlan_dfs_ucfg_api.c index c5195c9dd6..8d48a61743 100644 --- a/umac/dfs/dispatcher/src/wlan_dfs_ucfg_api.c +++ b/umac/dfs/dispatcher/src/wlan_dfs_ucfg_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. * * * Permission to use, copy, modify, and/or distribute this software for @@ -147,3 +147,31 @@ QDF_STATUS ucfg_dfs_get_precac_enable(struct wlan_objmgr_pdev *pdev, return QDF_STATUS_SUCCESS; } EXPORT_SYMBOL(ucfg_dfs_get_precac_enable); + +#ifdef QCA_MCL_DFS_SUPPORT +QDF_STATUS ucfg_dfs_update_config(struct wlan_objmgr_psoc *psoc, + struct dfs_user_config *req) +{ + struct dfs_soc_priv_obj *soc_obj; + + if (!psoc || !req) { + dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, + "psoc: 0x%pK, req: 0x%pK", psoc, req); + return QDF_STATUS_E_FAILURE; + } + + soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, + WLAN_UMAC_COMP_DFS); + if (!soc_obj) { + dfs_err(NULL, WLAN_DEBUG_DFS_ALWAYS, + "Failed to get dfs psoc component"); + return QDF_STATUS_E_FAILURE; + } + + soc_obj->dfs_is_phyerr_filter_offload = + req->dfs_is_phyerr_filter_offload; + + return QDF_STATUS_SUCCESS; +} +EXPORT_SYMBOL(ucfg_dfs_update_config); +#endif 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 59916f0555..765b959f5b 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 @@ -520,6 +520,7 @@ struct wlan_lmac_if_reg_tx_ops { * @dfs_reg_ev_handler: Register dfs event handler. * @dfs_process_emulate_bang_radar_cmd: Process emulate bang radar test command. * @dfs_is_pdev_5ghz: Check if the given pdev is 5GHz. + * @dfs_set_phyerr_filter_offload: Config phyerr filter offload. */ struct wlan_lmac_if_dfs_tx_ops { @@ -554,6 +555,9 @@ struct wlan_lmac_if_dfs_tx_ops { struct dfs_emulate_bang_radar_test_cmd *dfs_unit_test); QDF_STATUS (*dfs_is_pdev_5ghz)(struct wlan_objmgr_pdev *pdev, bool *is_5ghz); + QDF_STATUS (*dfs_set_phyerr_filter_offload)( + struct wlan_objmgr_pdev *pdev, + bool dfs_phyerr_filter_offload); }; /** @@ -963,6 +967,8 @@ struct wlan_lmac_if_nan_rx_ops { * @dfs_process_radar_ind: Process radar found indication. * @dfs_dfs_cac_complete_ind: Process cac complete indication. * @dfs_stop: Clear dfs timers. + * @dfs_process_phyerr_filter_offload:Process radar event. + * @dfs_is_phyerr_filter_offload: Check whether phyerr filter is offload. */ struct wlan_lmac_if_dfs_rx_ops { QDF_STATUS (*dfs_get_radars)(struct wlan_objmgr_pdev *pdev); @@ -1019,6 +1025,12 @@ struct wlan_lmac_if_dfs_rx_ops { uint32_t vdev_id); #endif QDF_STATUS (*dfs_stop)(struct wlan_objmgr_pdev *pdev); + QDF_STATUS (*dfs_process_phyerr_filter_offload)( + struct wlan_objmgr_pdev *pdev, + struct radar_event_info *wlan_radar_info); + QDF_STATUS (*dfs_is_phyerr_filter_offload)( + struct wlan_objmgr_pdev *pdev, + bool *is_phyerr_filter_offload); }; struct wlan_lmac_if_mlme_rx_ops { 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 245d57a142..1e29bb502d 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 @@ -301,6 +301,10 @@ wlan_lmac_if_umac_dfs_rx_ops_register(struct wlan_lmac_if_rx_ops *rx_ops) dfs_rx_ops->dfs_process_radar_ind = tgt_dfs_process_radar_ind; dfs_rx_ops->dfs_dfs_cac_complete_ind = tgt_dfs_cac_complete; dfs_rx_ops->dfs_stop = tgt_dfs_stop; + dfs_rx_ops->dfs_process_phyerr_filter_offload = + tgt_dfs_process_phyerr_filter_offload; + dfs_rx_ops->dfs_is_phyerr_filter_offload = + tgt_dfs_is_phyerr_filter_offload; return QDF_STATUS_SUCCESS; }