diff --git a/core/cds/src/cds_api.c b/core/cds/src/cds_api.c index b5af587fd75e..6a3d0391ea6f 100644 --- a/core/cds/src/cds_api.c +++ b/core/cds/src/cds_api.c @@ -827,6 +827,13 @@ CDF_STATUS cds_close(v_CONTEXT_t cds_context) { CDF_STATUS cdf_status; + cdf_status = wma_wmi_work_close(cds_context); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to close wma_wmi_work", __func__); + CDF_ASSERT(0); + } + if (gp_cds_context->htc_ctx) { htc_stop(gp_cds_context->htc_ctx); htc_destroy(gp_cds_context->htc_ctx); @@ -1534,6 +1541,13 @@ CDF_STATUS cds_shutdown(v_CONTEXT_t cds_context) } } + cdf_status = wma_wmi_work_close(cds_context); + if (!CDF_IS_STATUS_SUCCESS(cdf_status)) { + CDF_TRACE(CDF_MODULE_ID_CDF, CDF_TRACE_LEVEL_ERROR, + "%s: Failed to close wma_wmi_work!", __func__); + CDF_ASSERT(0); + } + if (gp_cds_context->htc_ctx) { htc_stop(gp_cds_context->htc_ctx); htc_destroy(gp_cds_context->htc_ctx); diff --git a/core/wma/inc/wma_api.h b/core/wma/inc/wma_api.h index ad78989f38ea..0e9b5f5bc559 100644 --- a/core/wma/inc/wma_api.h +++ b/core/wma/inc/wma_api.h @@ -90,6 +90,8 @@ CDF_STATUS wma_close(void *cds_context); CDF_STATUS wma_wmi_service_close(void *cds_context); +CDF_STATUS wma_wmi_work_close(void *cds_context); + void wma_rx_ready_event(WMA_HANDLE handle, void *ev); void wma_rx_service_ready_event(WMA_HANDLE handle, void *ev); diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index e9c6bd96bc47..9f4c36117018 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -2929,6 +2929,42 @@ CDF_STATUS wma_wmi_service_close(void *cds_ctx) return CDF_STATUS_SUCCESS; } +/** + * wma_wmi_work_close() - close the work queue items associated with WMI + * @cds_ctx: Pointer to cds context + * + * This function closes work queue items associated with WMI, but not fully + * closes WMI service. + * + * Return: CDF_STATUS_SUCCESS if work close is successful. Otherwise + * proper error codes. + */ +CDF_STATUS wma_wmi_work_close(void *cds_ctx) +{ + tp_wma_handle wma_handle; + + WMA_LOGD("%s: Enter", __func__); + + wma_handle = cds_get_context(CDF_MODULE_ID_WMA); + + /* validate the wma_handle */ + if (NULL == wma_handle) { + WMA_LOGE("%s: Invalid wma handle", __func__); + return CDF_STATUS_E_INVAL; + } + + /* validate the wmi handle */ + if (NULL == wma_handle->wmi_handle) { + WMA_LOGE("%s: Invalid wmi handle", __func__); + return CDF_STATUS_E_INVAL; + } + + /* remove the wmi work */ + WMA_LOGD("calling wmi_unified_remove_work"); + wmi_unified_remove_work(wma_handle->wmi_handle); + + return CDF_STATUS_SUCCESS; +} /** diff --git a/core/wmi/wmi_unified.c b/core/wmi/wmi_unified.c index 52a3ea5fedaa..c534fe508dd6 100644 --- a/core/wmi/wmi_unified.c +++ b/core/wmi/wmi_unified.c @@ -1128,6 +1128,36 @@ void wmi_unified_detach(struct wmi_unified *wmi_handle) } } +/** + * wmi_unified_remove_work() - detach for WMI work + * @wmi_handle: handle to WMI + * + * A function that does not fully detach WMI, but just remove work + * queue items associated with it. This is used to make sure that + * before any other processing code that may destroy related contexts + * (HTC, etc), work queue processing on WMI has already been stopped. + * + * Return: None + */ +void +wmi_unified_remove_work(struct wmi_unified *wmi_handle) +{ + wmi_buf_t buf; + + CDF_TRACE(CDF_MODULE_ID_WMI, CDF_TRACE_LEVEL_INFO, + "Enter: %s", __func__); + cds_flush_work(&wmi_handle->rx_event_work); + cdf_spin_lock_bh(&wmi_handle->eventq_lock); + buf = cdf_nbuf_queue_remove(&wmi_handle->event_queue); + while (buf) { + cdf_nbuf_free(buf); + buf = cdf_nbuf_queue_remove(&wmi_handle->event_queue); + } + cdf_spin_unlock_bh(&wmi_handle->eventq_lock); + CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_INFO, + "Done: %s", __func__); +} + void wmi_htc_tx_complete(void *ctx, HTC_PACKET *htc_pkt) { struct wmi_unified *wmi_handle = (struct wmi_unified *)ctx; diff --git a/core/wmi/wmi_unified_api.h b/core/wmi/wmi_unified_api.h index 5fc132206699..bcac971aa79e 100644 --- a/core/wmi/wmi_unified_api.h +++ b/core/wmi/wmi_unified_api.h @@ -57,6 +57,9 @@ void *wmi_unified_attach(void *scn_handle, */ void wmi_unified_detach(struct wmi_unified *wmi_handle); +void +wmi_unified_remove_work(struct wmi_unified *wmi_handle); + /** * generic function to allocate WMI buffer *