From bc62343617428bfaf85a164a3be29cd621274147 Mon Sep 17 00:00:00 2001 From: Rajeev Kumar Date: Wed, 29 Mar 2017 17:14:14 -0700 Subject: [PATCH] qcacmn: Migrate WMI from shared work queue to dedicated work queue WMI RX event processing is very critical for WLAN driver and today we are using kernel's shared event work queue. Shared event work queue is used by many drivers and if any work submitted in shared work queue takes longer time to finish then it directly impacts WLAN control path processing. Define a dedicated work queue for WMI RX event processing and use it for WMI RX event handling. Change-Id: I8ee6ca5b4b20c3357d46f8b56943078a0a76977f CRs-Fixed: 2029775 --- wmi/inc/wmi_unified_priv.h | 3 ++- wmi/src/wmi_unified.c | 49 ++++++++++++++++++++++++++++++-------- 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/wmi/inc/wmi_unified_priv.h b/wmi/inc/wmi_unified_priv.h index c3d3318a12..4a0f6ea7a6 100644 --- a/wmi/inc/wmi_unified_priv.h +++ b/wmi/inc/wmi_unified_priv.h @@ -1329,7 +1329,8 @@ struct wmi_unified { void *htc_handle; qdf_spinlock_t eventq_lock; qdf_nbuf_queue_t event_queue; - struct work_struct rx_event_work; + qdf_work_t rx_event_work; + qdf_workqueue_t *wmi_rx_work_queue; int wmi_stop_in_progress; #ifdef CONFIG_MCL struct _wmi_abi_version fw_abi_version; diff --git a/wmi/src/wmi_unified.c b/wmi/src/wmi_unified.c index 48c69b31f6..73b9d7a211 100644 --- a/wmi/src/wmi_unified.c +++ b/wmi/src/wmi_unified.c @@ -2285,7 +2285,9 @@ static void wmi_process_fw_event_worker_thread_ctx qdf_spin_lock_bh(&wmi_handle->eventq_lock); qdf_nbuf_queue_add(&wmi_handle->event_queue, evt_buf); qdf_spin_unlock_bh(&wmi_handle->eventq_lock); - schedule_work(&wmi_handle->rx_event_work); + qdf_queue_work(0, wmi_handle->wmi_rx_work_queue, + &wmi_handle->rx_event_work); + return; } @@ -2462,17 +2464,16 @@ end: /** * wmi_rx_event_work() - process rx event in rx work queue context - * @work: rx work queue struct + * @arg: opaque pointer to wmi handle * * This function process any fw event to serialize it through rx worker thread. * * Return: none */ -static void wmi_rx_event_work(struct work_struct *work) +static void wmi_rx_event_work(void *arg) { - struct wmi_unified *wmi = container_of(work, struct wmi_unified, - rx_event_work); wmi_buf_t buf; + struct wmi_unified *wmi = arg; qdf_spin_lock_bh(&wmi->eventq_lock); buf = qdf_nbuf_queue_remove(&wmi->event_queue); @@ -2596,7 +2597,6 @@ void *wmi_unified_get_pdev_handle(struct wmi_soc *soc, uint32_t pdev_idx) (struct wmi_unified *) qdf_mem_malloc( sizeof(struct wmi_unified)); if (wmi_handle == NULL) { - qdf_mem_free(soc); qdf_print("allocation of wmi handle failed %zu\n", sizeof(struct wmi_unified)); return NULL; @@ -2608,7 +2608,15 @@ void *wmi_unified_get_pdev_handle(struct wmi_soc *soc, uint32_t pdev_idx) wmi_handle->ops = soc->ops; qdf_spinlock_create(&wmi_handle->eventq_lock); qdf_nbuf_queue_init(&wmi_handle->event_queue); - INIT_WORK(&wmi_handle->rx_event_work, wmi_rx_event_work); + + qdf_create_work(0, &wmi_handle->rx_event_work, + wmi_rx_event_work, wmi_handle); + wmi_handle->wmi_rx_work_queue = + qdf_create_workqueue("wmi_rx_event_work_queue"); + if (NULL == wmi_handle->wmi_rx_work_queue) { + WMI_LOGE("failed to create wmi_rx_event_work_queue"); + goto error; + } wmi_handle->wmi_events = soc->wmi_events; wmi_target_params_init(soc, wmi_handle); wmi_interface_logging_init(wmi_handle); @@ -2624,6 +2632,11 @@ void *wmi_unified_get_pdev_handle(struct wmi_soc *soc, uint32_t pdev_idx) soc->wmi_pdev[pdev_idx] = wmi_handle; return wmi_handle; + +error: + qdf_mem_free(wmi_handle); + + return NULL; } /** @@ -2680,7 +2693,14 @@ void *wmi_unified_attach(void *scn_handle, wmi_runtime_pm_init(wmi_handle); qdf_spinlock_create(&wmi_handle->eventq_lock); qdf_nbuf_queue_init(&wmi_handle->event_queue); - INIT_WORK(&wmi_handle->rx_event_work, wmi_rx_event_work); + qdf_create_work(0, &wmi_handle->rx_event_work, + wmi_rx_event_work, wmi_handle); + wmi_handle->wmi_rx_work_queue = + qdf_create_workqueue("wmi_rx_event_work_queue"); + if (NULL == wmi_handle->wmi_rx_work_queue) { + WMI_LOGE("failed to create wmi_rx_event_work_queue"); + goto error; + } wmi_interface_logging_init(wmi_handle); /* Attach mc_thread context processing function */ wmi_handle->rx_ops.wma_process_fw_event_handler_cbk = @@ -2703,6 +2723,12 @@ void *wmi_unified_attach(void *scn_handle, soc->wmi_pdev[0] = wmi_handle; return wmi_handle; + +error: + qdf_mem_free(soc); + qdf_mem_free(wmi_handle); + + return NULL; } /** @@ -2721,7 +2747,10 @@ void wmi_unified_detach(struct wmi_unified *wmi_handle) soc = wmi_handle->soc; for (i = 0; i < WMI_MAX_RADIOS; i++) { if (soc->wmi_pdev[i]) { - cancel_work_sync(&soc->wmi_pdev[i]->rx_event_work); + qdf_flush_workqueue(0, + soc->wmi_pdev[i]->wmi_rx_work_queue); + qdf_destroy_workqueue(0, + soc->wmi_pdev[i]->wmi_rx_work_queue); wmi_debugfs_remove(soc->wmi_pdev[i]); buf = qdf_nbuf_queue_remove( &soc->wmi_pdev[i]->event_queue); @@ -2760,7 +2789,7 @@ wmi_unified_remove_work(struct wmi_unified *wmi_handle) QDF_TRACE(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_INFO, "Enter: %s", __func__); - cancel_work_sync(&wmi_handle->rx_event_work); + qdf_flush_workqueue(0, wmi_handle->wmi_rx_work_queue); qdf_spin_lock_bh(&wmi_handle->eventq_lock); buf = qdf_nbuf_queue_remove(&wmi_handle->event_queue); while (buf) {