1 /*
2  * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
3  * Copyright (c) 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 /**
21  * DOC: wlan_tdls_tgt_api.c
22  *
23  * TDLS south bound interface definitions
24  */
25 
26 #include "qdf_status.h"
27 #include <wlan_tdls_tgt_api.h>
28 #include "../../core/src/wlan_tdls_main.h"
29 #include "../../core/src/wlan_tdls_cmds_process.h"
30 #include "../../core/src/wlan_tdls_mgmt.h"
31 
32 static inline struct wlan_lmac_if_tdls_tx_ops *
wlan_psoc_get_tdls_txops(struct wlan_objmgr_psoc * psoc)33 wlan_psoc_get_tdls_txops(struct wlan_objmgr_psoc *psoc)
34 {
35 	return &psoc->soc_cb.tx_ops->tdls_tx_ops;
36 }
37 
38 static inline struct wlan_lmac_if_tdls_rx_ops *
wlan_psoc_get_tdls_rxops(struct wlan_objmgr_psoc * psoc)39 wlan_psoc_get_tdls_rxops(struct wlan_objmgr_psoc *psoc)
40 {
41 	return &psoc->soc_cb.rx_ops->tdls_rx_ops;
42 }
43 
tgt_tdls_set_fw_state(struct wlan_objmgr_psoc * psoc,struct tdls_info * tdls_param)44 QDF_STATUS tgt_tdls_set_fw_state(struct wlan_objmgr_psoc *psoc,
45 				 struct tdls_info *tdls_param)
46 {
47 	struct wlan_lmac_if_tdls_tx_ops *tdls_ops = NULL;
48 
49 	tdls_ops = wlan_psoc_get_tdls_txops(psoc);
50 	if (tdls_ops && tdls_ops->update_fw_state)
51 		return tdls_ops->update_fw_state(psoc, tdls_param);
52 	else
53 		return QDF_STATUS_SUCCESS;
54 }
55 
tgt_tdls_set_peer_state(struct wlan_objmgr_psoc * psoc,struct tdls_peer_update_state * peer_param)56 QDF_STATUS tgt_tdls_set_peer_state(struct wlan_objmgr_psoc *psoc,
57 				   struct tdls_peer_update_state *peer_param)
58 {
59 	struct wlan_lmac_if_tdls_tx_ops *tdls_ops = NULL;
60 
61 	tdls_ops = wlan_psoc_get_tdls_txops(psoc);
62 	if (tdls_ops && tdls_ops->update_peer_state)
63 		return tdls_ops->update_peer_state(psoc, peer_param);
64 	else
65 		return QDF_STATUS_SUCCESS;
66 }
67 
tgt_tdls_set_offchan_mode(struct wlan_objmgr_psoc * psoc,struct tdls_channel_switch_params * param)68 QDF_STATUS tgt_tdls_set_offchan_mode(struct wlan_objmgr_psoc *psoc,
69 				     struct tdls_channel_switch_params *param)
70 {
71 	struct wlan_lmac_if_tdls_tx_ops *tdls_ops = NULL;
72 
73 	tdls_ops = wlan_psoc_get_tdls_txops(psoc);
74 	if (tdls_ops && tdls_ops->set_offchan_mode)
75 		return tdls_ops->set_offchan_mode(psoc, param);
76 	else
77 		return QDF_STATUS_SUCCESS;
78 }
79 
tgt_tdls_send_mgmt_tx_completion(struct scheduler_msg * pmsg)80 QDF_STATUS tgt_tdls_send_mgmt_tx_completion(struct scheduler_msg *pmsg)
81 {
82 	QDF_STATUS status = QDF_STATUS_SUCCESS;
83 
84 	if (!pmsg || !pmsg->bodyptr) {
85 		tdls_err("msg: 0x%pK", pmsg);
86 		QDF_ASSERT(0);
87 		return QDF_STATUS_E_NULL_VALUE;
88 	}
89 
90 	status = tdls_send_mgmt_tx_completion(pmsg->bodyptr);
91 
92 	return status;
93 }
94 
tgt_tdls_send_mgmt_rsp(struct scheduler_msg * pmsg)95 QDF_STATUS tgt_tdls_send_mgmt_rsp(struct scheduler_msg *pmsg)
96 {
97 	QDF_STATUS status = QDF_STATUS_SUCCESS;
98 
99 	if (!pmsg || !pmsg->bodyptr) {
100 		tdls_err("msg: 0x%pK", pmsg);
101 		QDF_ASSERT(0);
102 		return QDF_STATUS_E_NULL_VALUE;
103 	}
104 
105 	status = tdls_process_send_mgmt_rsp(pmsg->bodyptr);
106 
107 	return status;
108 }
109 
tgt_tdls_add_peer_rsp(struct scheduler_msg * pmsg)110 QDF_STATUS tgt_tdls_add_peer_rsp(struct scheduler_msg *pmsg)
111 {
112 	QDF_STATUS status = QDF_STATUS_SUCCESS;
113 
114 	if (!pmsg || !pmsg->bodyptr) {
115 		tdls_err("msg: 0x%pK", pmsg);
116 		QDF_ASSERT(0);
117 		return QDF_STATUS_E_NULL_VALUE;
118 	}
119 
120 	status = tdls_process_add_peer_rsp(pmsg->bodyptr);
121 
122 	return status;
123 }
124 
tgt_tdls_del_peer_rsp(struct scheduler_msg * pmsg)125 QDF_STATUS tgt_tdls_del_peer_rsp(struct scheduler_msg *pmsg)
126 {
127 	QDF_STATUS status = QDF_STATUS_SUCCESS;
128 
129 	if (!pmsg || !pmsg->bodyptr) {
130 		tdls_err("msg: 0x%pK", pmsg);
131 		QDF_ASSERT(0);
132 		return QDF_STATUS_E_NULL_VALUE;
133 	}
134 
135 	status = tdls_process_del_peer_rsp(pmsg->bodyptr);
136 
137 	return status;
138 }
139 
tgt_tdls_register_ev_handler(struct wlan_objmgr_psoc * psoc)140 QDF_STATUS tgt_tdls_register_ev_handler(struct wlan_objmgr_psoc *psoc)
141 {
142 	struct wlan_lmac_if_tdls_tx_ops *tdls_ops = NULL;
143 
144 	tdls_ops = wlan_psoc_get_tdls_txops(psoc);
145 	if (tdls_ops && tdls_ops->tdls_reg_ev_handler)
146 		return tdls_ops->tdls_reg_ev_handler(psoc, NULL);
147 	else
148 		return QDF_STATUS_SUCCESS;
149 }
150 
tgt_tdls_unregister_ev_handler(struct wlan_objmgr_psoc * psoc)151 QDF_STATUS tgt_tdls_unregister_ev_handler(struct wlan_objmgr_psoc *psoc)
152 {
153 	struct wlan_lmac_if_tdls_tx_ops *tdls_ops = NULL;
154 
155 	tdls_ops = wlan_psoc_get_tdls_txops(psoc);
156 	if (tdls_ops->tdls_unreg_ev_handler)
157 		return tdls_ops->tdls_unreg_ev_handler(psoc, NULL);
158 	else
159 		return QDF_STATUS_SUCCESS;
160 }
161 
tgt_tdls_event_flush_cb(struct scheduler_msg * msg)162 static QDF_STATUS tgt_tdls_event_flush_cb(struct scheduler_msg *msg)
163 {
164 	struct tdls_event_notify *notify;
165 
166 	notify = msg->bodyptr;
167 	if (notify && notify->vdev) {
168 		wlan_objmgr_vdev_release_ref(notify->vdev, WLAN_TDLS_SB_ID);
169 		qdf_mem_free(notify);
170 	}
171 
172 	return QDF_STATUS_SUCCESS;
173 }
174 
175 QDF_STATUS
tgt_tdls_event_handler(struct wlan_objmgr_psoc * psoc,struct tdls_event_info * info)176 tgt_tdls_event_handler(struct wlan_objmgr_psoc *psoc,
177 		       struct tdls_event_info *info)
178 {
179 	struct scheduler_msg msg = {0,};
180 	struct tdls_event_notify *notify;
181 	uint8_t vdev_id;
182 	QDF_STATUS status;
183 
184 	if (!psoc || !info) {
185 		tdls_err("psoc: 0x%pK, info: 0x%pK", psoc, info);
186 		return QDF_STATUS_E_NULL_VALUE;
187 	}
188 	tdls_debug("vdev: %d, type: %d, reason: %d" QDF_MAC_ADDR_FMT,
189 		   info->vdev_id, info->message_type, info->peer_reason,
190 		   QDF_MAC_ADDR_REF(info->peermac.bytes));
191 	notify = qdf_mem_malloc(sizeof(*notify));
192 	if (!notify)
193 		return QDF_STATUS_E_NOMEM;
194 
195 	vdev_id = info->vdev_id;
196 	notify->vdev =
197 		wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
198 						     vdev_id, WLAN_TDLS_SB_ID);
199 	if (!notify->vdev) {
200 		tdls_err("null vdev, vdev_id: %d, psoc: 0x%pK", vdev_id, psoc);
201 		return QDF_STATUS_E_INVAL;
202 	}
203 	qdf_mem_copy(&notify->event, info, sizeof(*info));
204 
205 	msg.bodyptr = notify;
206 	msg.callback = tdls_process_evt;
207 	msg.flush_callback = tgt_tdls_event_flush_cb;
208 
209 	status = scheduler_post_message(QDF_MODULE_ID_TDLS,
210 					QDF_MODULE_ID_TDLS,
211 					QDF_MODULE_ID_TARGET_IF, &msg);
212 	if (QDF_IS_STATUS_ERROR(status)) {
213 		tdls_err("can't post msg to handle tdls event");
214 		wlan_objmgr_vdev_release_ref(notify->vdev, WLAN_TDLS_SB_ID);
215 		qdf_mem_free(notify);
216 	}
217 
218 	return status;
219 }
220 
tgt_tdls_mgmt_frame_rx_flush_cb(struct scheduler_msg * msg)221 static QDF_STATUS tgt_tdls_mgmt_frame_rx_flush_cb(struct scheduler_msg *msg)
222 {
223 	struct tdls_rx_mgmt_event *rx_mgmt_event;
224 
225 	rx_mgmt_event = msg->bodyptr;
226 
227 	if (rx_mgmt_event) {
228 		if (rx_mgmt_event->rx_mgmt)
229 			qdf_mem_free(rx_mgmt_event->rx_mgmt);
230 
231 		qdf_mem_free(rx_mgmt_event);
232 	}
233 	msg->bodyptr = NULL;
234 
235 	return QDF_STATUS_SUCCESS;
236 }
237 
238 static
tgt_tdls_mgmt_frame_process_rx_cb(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_peer * peer,qdf_nbuf_t buf,struct mgmt_rx_event_params * mgmt_rx_params,enum mgmt_frame_type frm_type)239 QDF_STATUS tgt_tdls_mgmt_frame_process_rx_cb(
240 			struct wlan_objmgr_psoc *psoc,
241 			struct wlan_objmgr_peer *peer,
242 			qdf_nbuf_t buf,
243 			struct mgmt_rx_event_params *mgmt_rx_params,
244 			enum mgmt_frame_type frm_type)
245 {
246 	struct tdls_rx_mgmt_frame *rx_mgmt;
247 	struct tdls_rx_mgmt_event *rx_mgmt_event;
248 	struct tdls_soc_priv_obj *tdls_soc_obj;
249 	struct scheduler_msg msg = {0};
250 	struct wlan_objmgr_vdev *vdev;
251 	uint32_t vdev_id;
252 	uint8_t *pdata;
253 	QDF_STATUS status;
254 
255 	tdls_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc,
256 			WLAN_UMAC_COMP_TDLS);
257 	if (!tdls_soc_obj) {
258 		tdls_err("tdls ctx is NULL, drop this frame");
259 		return QDF_STATUS_E_FAILURE;
260 	}
261 
262 	if (!peer) {
263 		vdev = tdls_get_vdev(psoc, WLAN_TDLS_SB_ID);
264 		if (!vdev) {
265 			tdls_err("current tdls vdev is null, can't get vdev id");
266 			return QDF_STATUS_E_FAILURE;
267 		}
268 		vdev_id = wlan_vdev_get_id(vdev);
269 		wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_SB_ID);
270 	} else {
271 		vdev = wlan_peer_get_vdev(peer);
272 		if (!vdev) {
273 			tdls_err("vdev is NULL in peer, drop this frame");
274 			return QDF_STATUS_E_FAILURE;
275 		}
276 		vdev_id = wlan_vdev_get_id(vdev);
277 	}
278 
279 	rx_mgmt_event = qdf_mem_malloc_atomic(sizeof(*rx_mgmt_event));
280 	if (!rx_mgmt_event)
281 		return QDF_STATUS_E_NOMEM;
282 
283 	rx_mgmt = qdf_mem_malloc_atomic(sizeof(*rx_mgmt) +
284 			mgmt_rx_params->buf_len);
285 	if (!rx_mgmt) {
286 		tdls_debug_rl("Failed to allocate rx mgmt frame");
287 		qdf_mem_free(rx_mgmt_event);
288 		return QDF_STATUS_E_NOMEM;
289 	}
290 
291 	pdata = (uint8_t *)qdf_nbuf_data(buf);
292 	rx_mgmt->frame_len = mgmt_rx_params->buf_len;
293 	rx_mgmt->rx_freq = mgmt_rx_params->chan_freq;
294 	rx_mgmt->vdev_id = vdev_id;
295 	rx_mgmt->frm_type = frm_type;
296 	rx_mgmt->rx_rssi = mgmt_rx_params->rssi;
297 
298 	rx_mgmt_event->rx_mgmt = rx_mgmt;
299 	rx_mgmt_event->tdls_soc_obj = tdls_soc_obj;
300 	qdf_mem_copy(rx_mgmt->buf, pdata, mgmt_rx_params->buf_len);
301 	msg.type = TDLS_EVENT_RX_MGMT;
302 	msg.bodyptr = rx_mgmt_event;
303 	msg.callback = tdls_process_rx_frame;
304 	msg.flush_callback = tgt_tdls_mgmt_frame_rx_flush_cb;
305 	status = scheduler_post_message(QDF_MODULE_ID_TDLS,
306 					QDF_MODULE_ID_TDLS,
307 					QDF_MODULE_ID_TARGET_IF, &msg);
308 	if (QDF_IS_STATUS_ERROR(status)) {
309 		qdf_mem_free(rx_mgmt);
310 		qdf_mem_free(rx_mgmt_event);
311 	}
312 
313 	qdf_nbuf_free(buf);
314 
315 	return status;
316 }
317 
tgt_tdls_mgmt_frame_rx_cb(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_peer * peer,qdf_nbuf_t buf,struct mgmt_rx_event_params * mgmt_rx_params,enum mgmt_frame_type frm_type)318 QDF_STATUS tgt_tdls_mgmt_frame_rx_cb(
319 			struct wlan_objmgr_psoc *psoc,
320 			struct wlan_objmgr_peer *peer,
321 			qdf_nbuf_t buf,
322 			struct mgmt_rx_event_params *mgmt_rx_params,
323 			enum mgmt_frame_type frm_type)
324 {
325 	QDF_STATUS status;
326 
327 	tdls_debug("psoc:%pK, peer:%pK, type:%d", psoc, peer, frm_type);
328 
329 
330 	if (!buf) {
331 		tdls_err("rx frame buff is null buf:%pK", buf);
332 		return QDF_STATUS_E_INVAL;
333 	}
334 
335 	if (!mgmt_rx_params || !psoc) {
336 		tdls_err("input is NULL mgmt_rx_params:%pK psoc:%pK, peer:%pK",
337 			  mgmt_rx_params, psoc, peer);
338 		status = QDF_STATUS_E_INVAL;
339 		goto release_nbuf;
340 	}
341 
342 	status = wlan_objmgr_peer_try_get_ref(peer, WLAN_TDLS_SB_ID);
343 	if (QDF_STATUS_SUCCESS != status)
344 		goto release_nbuf;
345 
346 	status = tgt_tdls_mgmt_frame_process_rx_cb(psoc, peer, buf,
347 						   mgmt_rx_params, frm_type);
348 
349 	wlan_objmgr_peer_release_ref(peer, WLAN_TDLS_SB_ID);
350 
351 	if (QDF_STATUS_SUCCESS != status)
352 release_nbuf:
353 		qdf_nbuf_free(buf);
354 	return status;
355 }
356 
tgt_tdls_peers_deleted_notification(struct wlan_objmgr_psoc * psoc,uint32_t session_id)357 void tgt_tdls_peers_deleted_notification(struct wlan_objmgr_psoc *psoc,
358 					 uint32_t session_id)
359 {
360 	tdls_peers_deleted_notification(psoc, session_id);
361 }
362 
tgt_tdls_delete_all_peers_indication(struct wlan_objmgr_psoc * psoc,uint32_t session_id)363 void tgt_tdls_delete_all_peers_indication(struct wlan_objmgr_psoc *psoc,
364 					  uint32_t session_id)
365 {
366 	tdls_check_and_indicate_delete_all_peers(psoc, session_id);
367 }
368