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(¬ify->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