summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbings <bings@codeaurora.org>2017-02-22 17:06:14 +0800
committerGerrit - the friendly Code Review server <code-review@localhost>2017-03-10 02:37:06 -0800
commit69ece0407effe881edd1d5ed9e295d059ff2b3a0 (patch)
treefadcfa7e7afc9866a28ad3654da0acc59e45d6ff
parent79fdfd47946a7b61b12dbc2c18d3f9b91b11fbbe (diff)
qcacld-2.0: Fix buffer exhausting caused by radar wmi event
Currently host driver may receive lots of radar wmi events in a short time because of hardware limitation, which may regard WiFi calibration signals as radar pulses. Driver allocates buffers for every wmi event in the interrupt bottom half and free these buffers in the wmi event work queue, so buffers may only be allocated and not freed when there are too many radar wmi events. Drop incoming radar wmi event if there is already 1000 radar wmi event pending. Change-Id: I20ab024bb87b5d883380796a9c080d1667d696ff CRs-Fixed: 1030466
-rw-r--r--CORE/SERVICES/WMA/wma.c4
-rw-r--r--CORE/SERVICES/WMA/wma.h2
-rw-r--r--CORE/SERVICES/WMI/wmi_unified.c22
3 files changed, 24 insertions, 4 deletions
diff --git a/CORE/SERVICES/WMA/wma.c b/CORE/SERVICES/WMA/wma.c
index 06436b39a266..1cbf9c84af32 100644
--- a/CORE/SERVICES/WMA/wma.c
+++ b/CORE/SERVICES/WMA/wma.c
@@ -7573,6 +7573,8 @@ static int wma_unified_dfs_radar_rx_event_handler(void *handle,
WMI_DFS_RADAR_EVENTID_param_tlvs *param_tlvs;
wmi_dfs_radar_event_fixed_param *radar_event;
+ adf_os_atomic_dec(&wma->dfs_wmi_event_pending);
+
ic = wma->dfs_ic;
if (NULL == ic) {
WMA_LOGE("%s: dfs_ic is NULL ", __func__);
@@ -9025,6 +9027,8 @@ VOS_STATUS WDA_open(v_VOID_t *vos_context, v_VOID_t *os_ctx,
adf_os_spinlock_init(&wma_handle->roam_synch_lock);
#endif
adf_os_atomic_init(&wma_handle->is_wow_bus_suspended);
+ adf_os_atomic_init(&wma_handle->dfs_wmi_event_pending);
+ adf_os_atomic_init(&wma_handle->dfs_wmi_event_dropped);
/* Register vdev start response event handler */
wmi_unified_register_event_handler(wma_handle->wmi_handle,
diff --git a/CORE/SERVICES/WMA/wma.h b/CORE/SERVICES/WMA/wma.h
index 4622bcbd1fce..a35a5008957a 100644
--- a/CORE/SERVICES/WMA/wma.h
+++ b/CORE/SERVICES/WMA/wma.h
@@ -849,6 +849,8 @@ typedef struct wma_handle {
int wow_nack;
u_int32_t ap_client_cnt;
adf_os_atomic_t is_wow_bus_suspended;
+ adf_os_atomic_t dfs_wmi_event_pending;
+ adf_os_atomic_t dfs_wmi_event_dropped;
vos_timer_t wma_scan_comp_timer;
scan_timer_info wma_scan_timer_info;
diff --git a/CORE/SERVICES/WMI/wmi_unified.c b/CORE/SERVICES/WMI/wmi_unified.c
index 150bd3ebec2e..4b0fbb6aff10 100644
--- a/CORE/SERVICES/WMI/wmi_unified.c
+++ b/CORE/SERVICES/WMI/wmi_unified.c
@@ -51,6 +51,7 @@
#endif
#define WMI_MIN_HEAD_ROOM 64
+#define RADAR_WMI_EVENT_PENDING_MAX 1000
#ifdef WMI_INTERFACE_EVENT_LOGGING
/* WMI commands */
@@ -1084,13 +1085,25 @@ void wmi_control_rx(void *ctx, HTC_PACKET *htc_packet)
int tlv_ok_status = 0;
u_int32_t id;
u_int8_t *data;
+ tp_wma_handle wma = wmi_handle->scn_handle;
evt_buf = (wmi_buf_t) htc_packet->pPktContext;
id = WMI_GET_FIELD(adf_nbuf_data(evt_buf), WMI_CMD_HDR, COMMANDID);
/* TX_PAUSE EVENT should be handled with tasklet context */
- if ((WMI_TX_PAUSE_EVENTID == id) ||
+ while ((WMI_TX_PAUSE_EVENTID == id) ||
(WMI_WOW_WAKEUP_HOST_EVENTID == id) ||
- (WMI_D0_WOW_DISABLE_ACK_EVENTID == id)) {
+ (WMI_D0_WOW_DISABLE_ACK_EVENTID == id) ||
+ (WMI_DFS_RADAR_EVENTID == id)) {
+ if ((WMI_DFS_RADAR_EVENTID == id) && wma) {
+ if (adf_os_atomic_inc_return(
+ &wma->dfs_wmi_event_pending) <
+ RADAR_WMI_EVENT_PENDING_MAX) {
+ break;
+ } else {
+ adf_os_atomic_inc(&wma->dfs_wmi_event_dropped);
+ adf_os_atomic_dec(&wma->dfs_wmi_event_pending);
+ }
+ }
if (adf_nbuf_pull_head(evt_buf, sizeof(WMI_CMD_HDR)) == NULL)
return;
@@ -1113,8 +1126,9 @@ void wmi_control_rx(void *ctx, HTC_PACKET *htc_packet)
adf_nbuf_free(evt_buf);
return;
}
- wmi_handle->event_handler[idx](wmi_handle->scn_handle,
- wmi_cmd_struct_ptr, len);
+ if (WMI_DFS_RADAR_EVENTID != id)
+ wmi_handle->event_handler[idx](wmi_handle->scn_handle,
+ wmi_cmd_struct_ptr, len);
wmitlv_free_allocated_event_tlvs(id, &wmi_cmd_struct_ptr);
adf_nbuf_free(evt_buf);
return;