Kaynağa Gözat

qcacmn: Hold a wakelock for management tx frames

Hold a timed wakelock whenever a management tx frame is sent, to
prevent issues around leaking descriptors or invalid access by firmware

Change-Id: If1a7ae69838791179b4a0365df3387146925509e
CRs-Fixed: 2033606
Dustin Brown 8 yıl önce
ebeveyn
işleme
1f271a1bd4

+ 13 - 1
umac/cmn_services/mgmt_txrx/core/src/wlan_mgmt_txrx_main.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017 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
@@ -125,6 +125,11 @@ struct mgmt_txrx_desc_elem_t *wlan_mgmt_txrx_desc_get(
 					  struct mgmt_txrx_desc_elem_t,
 					  entry);
 	mgmt_txrx_desc->in_use = true;
+
+	/* acquire the wakelock when there are pending mgmt tx frames */
+	qdf_wake_lock_timeout_acquire(&mgmt_txrx_ctx->wakelock_tx_cmp,
+				      MGMT_TXRX_WAKELOCK_TIMEOUT_TX_CMP);
+
 	qdf_spin_unlock_bh(&mgmt_txrx_ctx->mgmt_desc_pool.desc_pool_lock);
 
 	mgmt_txrx_info("retrieved mgmt desc: %p with desc id: %d",
@@ -142,6 +147,13 @@ void wlan_mgmt_txrx_desc_put(struct mgmt_txrx_priv_context *mgmt_txrx_ctx,
 	desc->in_use = false;
 	qdf_list_insert_front(&mgmt_txrx_ctx->mgmt_desc_pool.free_list,
 			      &desc->entry);
+
+	/* release the wakelock if there are no pending mgmt tx frames */
+	if (mgmt_txrx_ctx->mgmt_desc_pool.free_list.count ==
+	    mgmt_txrx_ctx->mgmt_desc_pool.free_list.max_size)
+		qdf_wake_lock_release(&mgmt_txrx_ctx->wakelock_tx_cmp,
+				      MGMT_TXRX_WAKELOCK_REASON_TX_CMP);
+
 	qdf_spin_unlock_bh(&mgmt_txrx_ctx->mgmt_desc_pool.desc_pool_lock);
 
 	mgmt_txrx_info("put mgmt desc: %p with desc id: %d into freelist",

+ 13 - 1
umac/cmn_services/mgmt_txrx/core/src/wlan_mgmt_txrx_main_i.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017 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
@@ -36,6 +36,16 @@
 #define IEEE80211_FC0_SUBTYPE_MASK          0xf0
 #define IEEE80211_FC0_TYPE_MGT              0x00
 
+/**
+ * mgmt_wakelock_reason - reasons mgmt_txrx might hold a wakelock
+ * @MGMT_TXRX_WAKELOCK_REASON_TX_CMP - wait for mgmt_tx_complete event
+ */
+enum mgmt_txrx_wakelock_reason {
+	MGMT_TXRX_WAKELOCK_REASON_TX_CMP
+};
+
+/* timeout to wait for management_tx_complete event from firmware */
+#define MGMT_TXRX_WAKELOCK_TIMEOUT_TX_CMP 300
 
 /*
  * generic definitions for IEEE 802.11 frames
@@ -165,6 +175,7 @@ struct mgmt_txrx_stats_t {
  * @mgmt_rx_comp_cb:  array of pointers of mgmt rx cbs
  * @mgmt_desc_pool:   pointer to mgmt desc. pool
  * @mgmt_txrx_stats:  pointer to mgmt txrx stats
+ * @wakelock_tx_cmp:  mgmt tx complete wake lock
  */
 struct mgmt_txrx_priv_context {
 	struct wlan_objmgr_psoc *psoc;
@@ -172,6 +183,7 @@ struct mgmt_txrx_priv_context {
 	struct mgmt_desc_pool_t mgmt_desc_pool;
 	struct mgmt_txrx_stats_t *mgmt_txrx_stats;
 	qdf_spinlock_t mgmt_txrx_ctx_lock;
+	qdf_wake_lock_t wakelock_tx_cmp;
 };
 
 

+ 4 - 0
umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_utils_api.c

@@ -80,6 +80,8 @@ static QDF_STATUS wlan_mgmt_txrx_psoc_obj_create_notification(
 	mgmt_txrx_ctx->mgmt_txrx_stats = mgmt_txrx_stats;
 
 	qdf_spinlock_create(&mgmt_txrx_ctx->mgmt_txrx_ctx_lock);
+	qdf_wake_lock_create(&mgmt_txrx_ctx->wakelock_tx_cmp,
+			     "mgmt_txrx tx_cmp");
 
 	if (wlan_objmgr_psoc_component_obj_attach(psoc,
 				WLAN_UMAC_COMP_MGMT_TXRX,
@@ -97,6 +99,7 @@ static QDF_STATUS wlan_mgmt_txrx_psoc_obj_create_notification(
 
 err_psoc_attach:
 	qdf_spinlock_destroy(&mgmt_txrx_ctx->mgmt_txrx_ctx_lock);
+	qdf_wake_lock_destroy(&mgmt_txrx_ctx->wakelock_tx_cmp);
 	qdf_mem_free(mgmt_txrx_stats);
 err_mgmt_txrx_stats:
 	wlan_mgmt_txrx_desc_pool_deinit(mgmt_txrx_ctx);
@@ -146,6 +149,7 @@ static QDF_STATUS wlan_mgmt_txrx_psoc_obj_destroy_notification(
 	wlan_mgmt_txrx_desc_pool_deinit(mgmt_txrx_ctx);
 	qdf_mem_free(mgmt_txrx_ctx->mgmt_txrx_stats);
 	qdf_spinlock_destroy(&mgmt_txrx_ctx->mgmt_txrx_ctx_lock);
+	qdf_wake_lock_destroy(&mgmt_txrx_ctx->wakelock_tx_cmp);
 	qdf_mem_free(mgmt_txrx_ctx);
 
 	mgmt_txrx_info("mgmt txrx deletion successful, psoc: %p", psoc);