xref: /wlan-dirver/qca-wifi-host-cmn/umac/cmn_services/mgmt_txrx/core/src/wlan_mgmt_txrx_main.c (revision 503663c6daafffe652fa360bde17243568cd6d2a)
1 /*
2  * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /**
20  *  DOC:    wlan_mgmt_txrx_main.c
21  *  This file contains mgmt txrx private API definitions for
22  *  mgmt txrx component.
23  */
24 
25 #include "wlan_mgmt_txrx_main_i.h"
26 #include "qdf_nbuf.h"
27 
28 QDF_STATUS wlan_mgmt_txrx_desc_pool_init(
29 			struct mgmt_txrx_priv_pdev_context *mgmt_txrx_pdev_ctx)
30 {
31 	uint32_t i;
32 
33 	mgmt_txrx_info(
34 			"mgmt_txrx ctx: %pK pdev: %pK mgmt desc pool size %d",
35 			mgmt_txrx_pdev_ctx, mgmt_txrx_pdev_ctx->pdev,
36 			MGMT_DESC_POOL_MAX);
37 	mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool = qdf_mem_malloc(
38 			MGMT_DESC_POOL_MAX *
39 			sizeof(struct mgmt_txrx_desc_elem_t));
40 
41 	if (!mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool)
42 		return QDF_STATUS_E_NOMEM;
43 
44 	qdf_list_create(&mgmt_txrx_pdev_ctx->mgmt_desc_pool.free_list,
45 					MGMT_DESC_POOL_MAX);
46 
47 	for (i = 0; i < MGMT_DESC_POOL_MAX; i++) {
48 		mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool[i].desc_id = i;
49 		mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool[i].in_use = false;
50 		qdf_list_insert_front(
51 				&mgmt_txrx_pdev_ctx->mgmt_desc_pool.free_list,
52 				&mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool[i].entry);
53 	}
54 
55 	qdf_spinlock_create(
56 		&mgmt_txrx_pdev_ctx->mgmt_desc_pool.desc_pool_lock);
57 
58 	return QDF_STATUS_SUCCESS;
59 }
60 
61 void wlan_mgmt_txrx_desc_pool_deinit(
62 			struct mgmt_txrx_priv_pdev_context *mgmt_txrx_pdev_ctx)
63 {
64 	uint32_t i;
65 	uint32_t pool_size;
66 	QDF_STATUS status;
67 
68 	if (!mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool) {
69 		mgmt_txrx_err("Empty mgmt descriptor pool");
70 		qdf_assert_always(0);
71 		return;
72 	}
73 
74 	pool_size = mgmt_txrx_pdev_ctx->mgmt_desc_pool.free_list.max_size;
75 	for (i = 0; i < pool_size; i++) {
76 		status = qdf_list_remove_node(
77 				&mgmt_txrx_pdev_ctx->mgmt_desc_pool.free_list,
78 				&mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool[i].entry);
79 		if (status != QDF_STATUS_SUCCESS)
80 			mgmt_txrx_err(
81 				"Failed to get mgmt desc from freelist, desc id: %d: status %d",
82 				i, status);
83 	}
84 
85 	qdf_list_destroy(&mgmt_txrx_pdev_ctx->mgmt_desc_pool.free_list);
86 	qdf_mem_free(mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool);
87 	mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool = NULL;
88 
89 	qdf_spinlock_destroy(
90 		&mgmt_txrx_pdev_ctx->mgmt_desc_pool.desc_pool_lock);
91 }
92 
93 struct mgmt_txrx_desc_elem_t *wlan_mgmt_txrx_desc_get(
94 			struct mgmt_txrx_priv_pdev_context *mgmt_txrx_pdev_ctx)
95 {
96 	QDF_STATUS status;
97 	qdf_list_node_t *desc_node;
98 	struct mgmt_txrx_desc_elem_t *mgmt_txrx_desc;
99 
100 	qdf_spin_lock_bh(&mgmt_txrx_pdev_ctx->mgmt_desc_pool.desc_pool_lock);
101 	if (qdf_list_peek_front(&mgmt_txrx_pdev_ctx->mgmt_desc_pool.free_list,
102 			    &desc_node)
103 			!= QDF_STATUS_SUCCESS) {
104 		qdf_spin_unlock_bh(
105 			&mgmt_txrx_pdev_ctx->mgmt_desc_pool.desc_pool_lock);
106 		mgmt_txrx_err("Descriptor freelist empty for mgmt_txrx_ctx %pK",
107 				mgmt_txrx_pdev_ctx);
108 		return NULL;
109 	}
110 
111 	status = qdf_list_remove_node(
112 				&mgmt_txrx_pdev_ctx->mgmt_desc_pool.free_list,
113 				desc_node);
114 	if (status != QDF_STATUS_SUCCESS) {
115 		qdf_spin_unlock_bh(
116 			&mgmt_txrx_pdev_ctx->mgmt_desc_pool.desc_pool_lock);
117 		mgmt_txrx_err("Failed to get descriptor from list: status %d",
118 					status);
119 		qdf_assert_always(0);
120 	}
121 
122 	mgmt_txrx_desc = qdf_container_of(desc_node,
123 					  struct mgmt_txrx_desc_elem_t,
124 					  entry);
125 	mgmt_txrx_desc->in_use = true;
126 
127 	qdf_spin_unlock_bh(&mgmt_txrx_pdev_ctx->mgmt_desc_pool.desc_pool_lock);
128 
129 	/* acquire the wakelock when there are pending mgmt tx frames */
130 	qdf_wake_lock_timeout_acquire(&mgmt_txrx_pdev_ctx->wakelock_tx_cmp,
131 				      MGMT_TXRX_WAKELOCK_TIMEOUT_TX_CMP);
132 	qdf_runtime_pm_prevent_suspend(
133 		&mgmt_txrx_pdev_ctx->wakelock_tx_runtime_cmp);
134 
135 
136 	return mgmt_txrx_desc;
137 }
138 
139 void wlan_mgmt_txrx_desc_put(
140 			struct mgmt_txrx_priv_pdev_context *mgmt_txrx_pdev_ctx,
141 			uint32_t desc_id)
142 {
143 	struct mgmt_txrx_desc_elem_t *desc;
144 	bool release_wakelock = false;
145 
146 	desc = &mgmt_txrx_pdev_ctx->mgmt_desc_pool.pool[desc_id];
147 	qdf_spin_lock_bh(&mgmt_txrx_pdev_ctx->mgmt_desc_pool.desc_pool_lock);
148 	if (!desc->in_use) {
149 		qdf_spin_unlock_bh(&mgmt_txrx_pdev_ctx->mgmt_desc_pool.
150 				   desc_pool_lock);
151 		mgmt_txrx_err("desc %d is freed", desc_id);
152 		return;
153 	}
154 	desc->in_use = false;
155 	desc->context = NULL;
156 	desc->peer = NULL;
157 	desc->nbuf = NULL;
158 	desc->tx_dwnld_cmpl_cb = NULL;
159 	desc->tx_ota_cmpl_cb = NULL;
160 	desc->vdev_id = WLAN_UMAC_VDEV_ID_MAX;
161 
162 	qdf_list_insert_front(&mgmt_txrx_pdev_ctx->mgmt_desc_pool.free_list,
163 			      &desc->entry);
164 
165 	/* release the wakelock if there are no pending mgmt tx frames */
166 	if (mgmt_txrx_pdev_ctx->mgmt_desc_pool.free_list.count ==
167 	    mgmt_txrx_pdev_ctx->mgmt_desc_pool.free_list.max_size)
168 		release_wakelock = true;
169 
170 	qdf_spin_unlock_bh(&mgmt_txrx_pdev_ctx->mgmt_desc_pool.desc_pool_lock);
171 
172 	if (release_wakelock) {
173 		qdf_runtime_pm_allow_suspend(
174 			&mgmt_txrx_pdev_ctx->wakelock_tx_runtime_cmp);
175 		qdf_wake_lock_release(&mgmt_txrx_pdev_ctx->wakelock_tx_cmp,
176 				      MGMT_TXRX_WAKELOCK_REASON_TX_CMP);
177 	}
178 }
179