Kaynağa Gözat

qcacmn: channel_switch_complete_evt need wake up all waiting threads

2 threads blocked to wait channel_switch_complete_evt for SAP channel
switch is already in progress,  qdf_event_set only woke up 1st thread
later,  2nd  thread still kept blocked with hold  net_dev for debug id
NET_DEV_HOLD_COUNTRY_CHANGE_UPDATE_SAP, leak happened.

Change-Id: Ib76318dd4a613ca1852a56b7701a04385b69ba56
CRs-Fixed: 3061976
Jianmin Zhu 3 yıl önce
ebeveyn
işleme
7a0af0ae4e
2 değiştirilmiş dosya ile 49 ekleme ve 14 silme
  1. 29 1
      qdf/inc/qdf_event.h
  2. 20 13
      qdf/linux/src/qdf_event.c

+ 29 - 1
qdf/inc/qdf_event.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2018, 2021 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -41,8 +41,36 @@ typedef __qdf_event_t qdf_event_t;
 
 QDF_STATUS qdf_event_create(qdf_event_t *event);
 
+/**
+ * qdf_event_set() - sets a QDF event for single waiting threads
+ * @event: The event to set to the signalled state
+ *
+ * The state of the specified event is set to signalled by calling
+ * qdf_event_set().
+ *
+ * Single thread waiting on the event as a result of a qdf_event_wait() will
+ * be unblocked and available to be scheduled for execution when the event
+ * is signaled by a call to qdf_event_set().
+ *
+ * Return: QDF status
+ */
 QDF_STATUS qdf_event_set(qdf_event_t *event);
 
+/**
+ * qdf_event_set_all() - sets a QDF event for all waiting threads
+ * @event: The event to set to the signalled state
+ *
+ * The state of the specified event is set to signalled by calling
+ * qdf_event_set_all().
+ *
+ * Any threads waiting on the event as a result of a qdf_event_wait() will
+ * be unblocked and available to be scheduled for execution when the event
+ * is signaled by a call to qdf_event_set().
+ *
+ * Return: QDF status
+ */
+QDF_STATUS qdf_event_set_all(qdf_event_t *event);
+
 QDF_STATUS qdf_event_reset(qdf_event_t *event);
 
 QDF_STATUS qdf_event_destroy(qdf_event_t *event);

+ 20 - 13
qdf/linux/src/qdf_event.c

@@ -77,19 +77,6 @@ QDF_STATUS qdf_event_create(qdf_event_t *event)
 }
 qdf_export_symbol(qdf_event_create);
 
-/**
- * qdf_event_set() - sets a QDF event
- * @event: The event to set to the signalled state
- *
- * The state of the specified event is set to signalled by calling
- * qdf_event_set().
- *
- * Any threads waiting on the event as a result of a qdf_event_wait() will
- * be unblocked and available to be scheduled for execution when the event
- * is signaled by a call to qdf_event_set().
- *
- * Return: QDF status
- */
 QDF_STATUS qdf_event_set(qdf_event_t *event)
 {
 	QDF_BUG(event);
@@ -106,8 +93,28 @@ QDF_STATUS qdf_event_set(qdf_event_t *event)
 
 	return QDF_STATUS_SUCCESS;
 }
+
 qdf_export_symbol(qdf_event_set);
 
+QDF_STATUS qdf_event_set_all(qdf_event_t *event)
+{
+	QDF_BUG(event);
+	if (!event)
+		return QDF_STATUS_E_FAULT;
+
+	/* ensure event is initialized */
+	QDF_BUG(event->cookie == LINUX_EVENT_COOKIE);
+	if (event->cookie != LINUX_EVENT_COOKIE)
+		return QDF_STATUS_E_INVAL;
+
+	event->done = true;
+	complete_all(&event->complete);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+qdf_export_symbol(qdf_event_set_all);
+
 /**
  * qdf_event_reset() - resets a QDF event
  * @event: The event to set to the NOT signalled state