diff options
| author | bings <bings@codeaurora.org> | 2017-02-22 17:06:14 +0800 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2017-03-10 02:37:06 -0800 |
| commit | 69ece0407effe881edd1d5ed9e295d059ff2b3a0 (patch) | |
| tree | fadcfa7e7afc9866a28ad3654da0acc59e45d6ff | |
| parent | 79fdfd47946a7b61b12dbc2c18d3f9b91b11fbbe (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.c | 4 | ||||
| -rw-r--r-- | CORE/SERVICES/WMA/wma.h | 2 | ||||
| -rw-r--r-- | CORE/SERVICES/WMI/wmi_unified.c | 22 |
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; |
