1 /*
2  * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include "qdf_mem.h"
21 #include "qdf_module.h"
22 #include "wlan_lmac_if_def.h"
23 #include "wlan_lmac_if_api.h"
24 #include "wlan_global_lmac_if_api.h"
25 #ifdef WLAN_CONV_SPECTRAL_ENABLE
26 #include <wlan_spectral_utils_api.h>
27 #endif
28 #include <target_if_psoc_wake_lock.h>
29 
30 /* Function pointer to call DA/OL specific tx_ops registration function */
31 QDF_STATUS (*wlan_global_lmac_if_tx_ops_register[MAX_DEV_TYPE])
32 				(struct wlan_lmac_if_tx_ops *tx_ops);
33 
34 /*
35  * spectral scan is built as separate .ko for WIN where
36  * MCL it is part of wlan.ko so the registration of
37 .* rx ops to global lmac if layer is different between WIN
38  * and MCL
39  */
40 #ifdef WLAN_CONV_SPECTRAL_ENABLE
41 #ifdef SPECTRAL_MODULIZED_ENABLE
42 /* Function pointer for spectral rx_ops registration function */
43 void (*wlan_lmac_if_sptrl_rx_ops)(struct wlan_lmac_if_rx_ops *rx_ops);
44 
wlan_lmac_if_sptrl_set_rx_ops_register_cb(void (* handler)(struct wlan_lmac_if_rx_ops *))45 QDF_STATUS wlan_lmac_if_sptrl_set_rx_ops_register_cb(void (*handler)
46 				(struct wlan_lmac_if_rx_ops *))
47 {
48 	wlan_lmac_if_sptrl_rx_ops = handler;
49 
50 	return QDF_STATUS_SUCCESS;
51 }
52 
53 qdf_export_symbol(wlan_lmac_if_sptrl_set_rx_ops_register_cb);
54 
55 /**
56  * wlan_spectral_register_rx_ops() - Register spectral component RX OPS
57  * @rx_ops: lmac if receive ops
58  *
59  * Return: None
60  */
wlan_spectral_register_rx_ops(struct wlan_lmac_if_rx_ops * rx_ops)61 static void wlan_spectral_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops)
62 {
63 	wlan_lmac_if_sptrl_rx_ops(rx_ops);
64 }
65 #else
wlan_spectral_register_rx_ops(struct wlan_lmac_if_rx_ops * rx_ops)66 static void wlan_spectral_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops)
67 {
68 	wlan_lmac_if_sptrl_register_rx_ops(rx_ops);
69 }
70 #endif /* SPECTRAL_MODULIZED_ENABLE */
71 #else
72 /**
73  * wlan_spectral_register_rx_ops() - Dummy api to register spectral RX OPS
74  * @rx_ops: lmac if receive ops
75  *
76  * Return: None
77  */
wlan_spectral_register_rx_ops(struct wlan_lmac_if_rx_ops * rx_ops)78 static void wlan_spectral_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops)
79 {
80 }
81 #endif /*WLAN_CONV_SPECTRAL_ENABLE*/
82 
83 #ifdef WLAN_IOT_SIM_SUPPORT
84 /* Function pointer for iot_sim rx_ops registration function */
85 void (*wlan_lmac_if_iot_sim_rx_ops)(struct wlan_lmac_if_rx_ops *rx_ops);
86 
wlan_lmac_if_iot_sim_set_rx_ops_register_cb(void (* handler)(struct wlan_lmac_if_rx_ops *))87 QDF_STATUS wlan_lmac_if_iot_sim_set_rx_ops_register_cb(void (*handler)
88 				(struct wlan_lmac_if_rx_ops *))
89 {
90 	wlan_lmac_if_iot_sim_rx_ops = handler;
91 
92 	return QDF_STATUS_SUCCESS;
93 }
94 
95 qdf_export_symbol(wlan_lmac_if_iot_sim_set_rx_ops_register_cb);
96 
wlan_iot_sim_register_rx_ops(struct wlan_lmac_if_rx_ops * rx_ops)97 static void wlan_iot_sim_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops)
98 {
99 	if (wlan_lmac_if_iot_sim_rx_ops)
100 		wlan_lmac_if_iot_sim_rx_ops(rx_ops);
101 	else
102 		qdf_print("\n***** IOT SIM MODULE NOT LOADED *****\n");
103 }
104 
105 #else
wlan_iot_sim_register_rx_ops(struct wlan_lmac_if_rx_ops * rx_ops)106 static void wlan_iot_sim_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops)
107 {
108 }
109 #endif
110 
111 #if defined(QCA_SUPPORT_SON) || defined(WLAN_FEATURE_SON)
112 /* Function pointer for son rx_ops registration function */
113 void (*wlan_lmac_if_son_rx_ops)(struct wlan_lmac_if_rx_ops *rx_ops);
114 
wlan_lmac_if_son_set_rx_ops_register_cb(void (* handler)(struct wlan_lmac_if_rx_ops *))115 QDF_STATUS wlan_lmac_if_son_set_rx_ops_register_cb(void (*handler)
116 				(struct wlan_lmac_if_rx_ops *))
117 {
118 	wlan_lmac_if_son_rx_ops = handler;
119 
120 	return QDF_STATUS_SUCCESS;
121 }
122 
123 qdf_export_symbol(wlan_lmac_if_son_set_rx_ops_register_cb);
124 
wlan_son_register_rx_ops(struct wlan_lmac_if_rx_ops * rx_ops)125 static void wlan_son_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops)
126 {
127 	if (wlan_lmac_if_son_rx_ops)
128 		wlan_lmac_if_son_rx_ops(rx_ops);
129 	else
130 		qdf_info("\n***** SON MODULE NOT LOADED *****\n");
131 }
132 
wlan_lmac_if_son_mod_register_rx_ops(struct wlan_lmac_if_rx_ops * rx_ops)133 void wlan_lmac_if_son_mod_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops)
134 {
135 	wlan_son_register_rx_ops(rx_ops);
136 }
137 #else
wlan_son_register_rx_ops(struct wlan_lmac_if_rx_ops * rx_ops)138 static void wlan_son_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops)
139 {
140 }
141 #endif
142 
143 /**
144  * wlan_global_lmac_if_rx_ops_register() - Global lmac_if
145  * rx handler register
146  * @rx_ops: Pointer to rx_ops structure to be populated
147  *
148  * Register lmac_if RX callabacks which will be called by DA/OL/WMA/WMI
149  *
150  * Return: QDF_STATUS_SUCCESS - in case of success
151  */
152 QDF_STATUS
wlan_global_lmac_if_rx_ops_register(struct wlan_lmac_if_rx_ops * rx_ops)153 wlan_global_lmac_if_rx_ops_register(struct wlan_lmac_if_rx_ops *rx_ops)
154 {
155 	/*
156 	 * Component specific public api's to be called to register
157 	 * respective callbacks
158 	 * Ex: rx_ops->fp = function;
159 	 */
160 	if (!rx_ops) {
161 		qdf_err("lmac if rx ops pointer is NULL");
162 		return QDF_STATUS_E_INVAL;
163 	}
164 	/* Registration for UMAC components */
165 	wlan_lmac_if_umac_rx_ops_register(rx_ops);
166 
167 	/* spectral rx_ops registration*/
168 	wlan_spectral_register_rx_ops(rx_ops);
169 
170 	/* iot_sim rx_ops registration*/
171 	wlan_iot_sim_register_rx_ops(rx_ops);
172 
173 	/* son rx_ops registration*/
174 	wlan_son_register_rx_ops(rx_ops);
175 
176 	return QDF_STATUS_SUCCESS;
177 }
178 
179 /**
180  * wlan_global_lmac_if_open() - global lmac_if open
181  * @psoc: psoc context
182  *
183  * Opens up lmac_if southbound layer. This function calls OL,DA and UMAC
184  * modules to register respective tx and rx callbacks.
185  *
186  * Return: QDF_STATUS
187  */
wlan_global_lmac_if_open(struct wlan_objmgr_psoc * psoc)188 QDF_STATUS wlan_global_lmac_if_open(struct wlan_objmgr_psoc *psoc)
189 {
190 	WLAN_DEV_TYPE dev_type;
191 
192 	struct wlan_lmac_if_tx_ops *tx_ops;
193 	struct wlan_lmac_if_rx_ops *rx_ops;
194 
195 	if (!psoc) {
196 		qdf_err("psoc is NULL");
197 		return QDF_STATUS_E_INVAL;
198 	}
199 
200 	tx_ops = qdf_mem_malloc(sizeof(*tx_ops));
201 	if (!tx_ops) {
202 		qdf_err("tx_ops is NULL");
203 		return QDF_STATUS_E_NOMEM;
204 	}
205 
206 	rx_ops = qdf_mem_malloc(sizeof(*rx_ops));
207 	if (!rx_ops) {
208 		qdf_err("rx_ops is NULL");
209 		qdf_mem_free(tx_ops);
210 		return QDF_STATUS_E_NOMEM;
211 	}
212 
213 	wlan_psoc_set_lmac_if_txops(psoc, tx_ops);
214 	wlan_psoc_set_lmac_if_rxops(psoc, rx_ops);
215 
216 	dev_type = psoc->soc_nif.phy_type;
217 
218 	if (dev_type == WLAN_DEV_OL) {
219 		wlan_global_lmac_if_tx_ops_register[dev_type]
220 					(tx_ops);
221 	} else {
222 		/* Control should ideally not reach here */
223 		qdf_print("Invalid device type");
224 		qdf_mem_free(tx_ops);
225 		qdf_mem_free(rx_ops);
226 		return QDF_STATUS_E_INVAL;
227 	}
228 
229 	/* Function call to register rx-ops handlers */
230 	wlan_global_lmac_if_rx_ops_register(rx_ops);
231 
232 	target_if_wake_lock_init(psoc);
233 
234 	return QDF_STATUS_SUCCESS;
235 }
236 qdf_export_symbol(wlan_global_lmac_if_open);
237 
238 /**
239  * wlan_global_lmac_if_close() - Close global lmac_if
240  * @psoc: psoc context
241  *
242  * Deregister lmac_if TX and RX handlers
243  *
244  * Return: QDF_STATUS_SUCCESS - in case of success
245  */
wlan_global_lmac_if_close(struct wlan_objmgr_psoc * psoc)246 QDF_STATUS wlan_global_lmac_if_close(struct wlan_objmgr_psoc *psoc)
247 {
248 	struct wlan_lmac_if_tx_ops *tx_ops;
249 	struct wlan_lmac_if_rx_ops *rx_ops;
250 
251 	if (!psoc) {
252 		qdf_err("psoc is NULL");
253 		return QDF_STATUS_E_INVAL;
254 	}
255 
256 	target_if_wake_lock_deinit(psoc);
257 	tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
258 	rx_ops = wlan_psoc_get_lmac_if_rxops(psoc);
259 
260 	wlan_psoc_set_lmac_if_txops(psoc, NULL);
261 	wlan_psoc_set_lmac_if_rxops(psoc, NULL);
262 
263 	qdf_mem_free(tx_ops);
264 	qdf_mem_free(rx_ops);
265 
266 	return QDF_STATUS_SUCCESS;
267 }
268 qdf_export_symbol(wlan_global_lmac_if_close);
269 
270 /**
271  * wlan_global_lmac_if_set_txops_registration_cb() - tx
272  * registration callback assignment
273  * @dev_type: Dev type can be either Direct attach or Offload
274  * @handler: handler to be called for LMAC tx ops registration
275  *
276  * API to assign appropriate tx registration callback handler based on the
277  * device type(Offload or Direct attach)
278  *
279  * Return: QDF_STATUS_SUCCESS - in case of success
280  */
wlan_global_lmac_if_set_txops_registration_cb(WLAN_DEV_TYPE dev_type,QDF_STATUS (* handler)(struct wlan_lmac_if_tx_ops *))281 QDF_STATUS wlan_global_lmac_if_set_txops_registration_cb(WLAN_DEV_TYPE dev_type,
282 			QDF_STATUS (*handler)(struct wlan_lmac_if_tx_ops *))
283 {
284 	wlan_global_lmac_if_tx_ops_register[dev_type] = handler;
285 
286 	return QDF_STATUS_SUCCESS;
287 }
288 qdf_export_symbol(wlan_global_lmac_if_set_txops_registration_cb);
289