Explorar o código

qcacld-3.0: Gracefully deregister packet capture callbacks

Deregistering packet capture callbacks can call while
processing mon thread which can lead to race condition.

To address this, deregister packet capture callbacks after
mon thread successfully processes its current packet.

Change-Id: I09640128a57ef6adac4e6a025cb81667e49b6e4c
CRs-Fixed: 2735587
Vulupala Shashank Reddy %!s(int64=4) %!d(string=hai) anos
pai
achega
f03bd42cdc

+ 3 - 0
components/pkt_capture/core/inc/wlan_pkt_capture_mon_thread.h

@@ -28,6 +28,7 @@
 #define PKT_CAPTURE_RX_POST_EVENT 0x01
 #define PKT_CAPTURE_RX_SUSPEND_EVENT 0x02
 #define PKT_CAPTURE_RX_SHUTDOWN_EVENT 0x04
+#define PKT_CAPTURE_REGISTER_EVENT 0x08
 
 /*
  * Maximum number of packets to be allocated for
@@ -81,6 +82,7 @@ struct pkt_capture_mon_pkt {
  * @suspend_mon_event: Completion to suspend packet capture MON thread
  * @resume_mon_event: Completion to resume packet capture MON thread
  * @mon_shutdown: Completion for packet capture MON thread shutdown
+ * @mon_register_event: Completion for packet capture register
  * @mon_wait_queue: Waitq for packet capture MON thread
  * @mon_event_flag: Mon event flag
  * @mon_thread_queue: MON buffer queue
@@ -97,6 +99,7 @@ struct pkt_capture_mon_context {
 	struct completion suspend_mon_event;
 	struct completion resume_mon_event;
 	struct completion mon_shutdown;
+	struct completion mon_register_event;
 	wait_queue_head_t mon_wait_queue;
 	unsigned long mon_event_flag;
 	struct list_head mon_thread_queue;

+ 24 - 0
components/pkt_capture/core/src/wlan_pkt_capture_main.c

@@ -98,6 +98,13 @@ pkt_capture_register_callbacks(struct wlan_objmgr_vdev *vdev,
 	if (QDF_IS_STATUS_ERROR(status))
 		goto register_ev_handlers_fail;
 
+	/*
+	 * set register event bit so that mon thread will start
+	 * processing packets in queue.
+	 */
+	set_bit(PKT_CAPTURE_REGISTER_EVENT,
+		&vdev_priv->mon_ctx->mon_event_flag);
+
 	mode = pkt_capture_get_mode(psoc);
 	status = tgt_pkt_capture_send_mode(vdev, mode);
 	if (QDF_IS_STATUS_ERROR(status)) {
@@ -145,6 +152,23 @@ QDF_STATUS pkt_capture_deregister_callbacks(struct wlan_objmgr_vdev *vdev)
 	if (QDF_IS_STATUS_ERROR(status))
 		pkt_capture_err("Unable to send packet capture mode to fw");
 
+	/*
+	 * Clear packet capture register event so that mon thread will
+	 * stop processing packets in queue.
+	 */
+	clear_bit(PKT_CAPTURE_REGISTER_EVENT,
+		  &vdev_priv->mon_ctx->mon_event_flag);
+	set_bit(PKT_CAPTURE_RX_POST_EVENT,
+		&vdev_priv->mon_ctx->mon_event_flag);
+	wake_up_interruptible(&vdev_priv->mon_ctx->mon_wait_queue);
+
+	/*
+	 * Wait till current packet process completes in mon thread and
+	 * flush the remaining packet in queue.
+	 */
+	wait_for_completion(&vdev_priv->mon_ctx->mon_register_event);
+	pkt_capture_drop_monpkt(vdev_priv->mon_ctx);
+
 	status = tgt_pkt_capture_unregister_ev_handler(vdev);
 	if (QDF_IS_STATUS_ERROR(status))
 		pkt_capture_err("Unable to unregister event handlers");

+ 13 - 2
components/pkt_capture/core/src/wlan_pkt_capture_mon_thread.c

@@ -331,7 +331,17 @@ static int pkt_capture_mon_thread(void *arg)
 				shutdown = true;
 				break;
 			}
-			pkt_capture_process_from_queue(mon_ctx);
+
+			/*
+			 * if packet capture deregistratin happens stop
+			 * processing packets in queue because mon cb will
+			 * be set to NULL.
+			 */
+			if (test_bit(PKT_CAPTURE_REGISTER_EVENT,
+				     &mon_ctx->mon_event_flag))
+				pkt_capture_process_from_queue(mon_ctx);
+			else
+				complete(&mon_ctx->mon_register_event);
 
 			if (test_bit(PKT_CAPTURE_RX_SUSPEND_EVENT,
 				     &mon_ctx->mon_event_flag)) {
@@ -358,7 +368,7 @@ void pkt_capture_close_mon_thread(struct pkt_capture_mon_context *mon_ctx)
 	if (!mon_ctx->mon_thread)
 		return;
 
-	/* Shut down Tlshim Rx thread */
+	/* Shut down mon thread */
 	set_bit(PKT_CAPTURE_RX_SHUTDOWN_EVENT,
 		&mon_ctx->mon_event_flag);
 	set_bit(PKT_CAPTURE_RX_POST_EVENT,
@@ -494,6 +504,7 @@ pkt_capture_alloc_mon_thread(struct pkt_capture_mon_context *mon_ctx)
 	init_completion(&mon_ctx->suspend_mon_event);
 	init_completion(&mon_ctx->resume_mon_event);
 	init_completion(&mon_ctx->mon_shutdown);
+	init_completion(&mon_ctx->mon_register_event);
 	mon_ctx->mon_event_flag = 0;
 	spin_lock_init(&mon_ctx->mon_queue_lock);
 	spin_lock_init(&mon_ctx->mon_pkt_freeq_lock);