瀏覽代碼

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
Rajeev Kumar 8 年之前
父節點
當前提交
bc62343617
共有 2 個文件被更改,包括 41 次插入11 次删除
  1. 2 1
      wmi/inc/wmi_unified_priv.h
  2. 39 10
      wmi/src/wmi_unified.c

+ 2 - 1
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;

+ 39 - 10
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) {