1 /*
2 * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 /**
18 * DOC: wma_pasn_peer_api.c
19 * This file contains PASN peer related operations.
20 */
21
22 #include "wma.h"
23 #include "wma_api.h"
24 #include "wmi_unified_api.h"
25 #include "wmi_unified.h"
26 #include "qdf_types.h"
27 #include "qdf_mem.h"
28 #include "wma_types.h"
29 #include "wma_internal.h"
30 #include "wma_pasn_peer_api.h"
31 #include "wifi_pos_pasn_api.h"
32 #include "wifi_pos_api.h"
33 #include "init_deinit_lmac.h"
34
35 QDF_STATUS
wma_pasn_peer_remove(struct wlan_objmgr_psoc * psoc,struct qdf_mac_addr * peer_addr,uint8_t vdev_id,bool no_fw_peer_delete)36 wma_pasn_peer_remove(struct wlan_objmgr_psoc *psoc,
37 struct qdf_mac_addr *peer_addr,
38 uint8_t vdev_id, bool no_fw_peer_delete)
39 {
40 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
41 struct peer_delete_cmd_params del_param = {0};
42 QDF_STATUS qdf_status;
43 uint8_t peer_vdev_id;
44
45 if (!wma) {
46 wma_err("wma_handle is NULL");
47 return QDF_STATUS_E_INVAL;
48 }
49
50 if (!wma_objmgr_peer_exist(wma, peer_addr->bytes, &peer_vdev_id)) {
51 wma_err("peer doesn't exist peer_addr " QDF_MAC_ADDR_FMT " vdevid %d",
52 QDF_MAC_ADDR_REF(peer_addr->bytes), vdev_id);
53 return QDF_STATUS_E_INVAL;
54 }
55
56 if (peer_vdev_id != vdev_id) {
57 wma_err("peer " QDF_MAC_ADDR_FMT " is on vdev id %d but delete req on vdevid %d",
58 QDF_MAC_ADDR_REF(peer_addr->bytes),
59 peer_vdev_id, vdev_id);
60 return QDF_STATUS_E_INVAL;
61 }
62
63 del_param.vdev_id = vdev_id;
64 qdf_status = wmi_unified_peer_delete_send(wma->wmi_handle,
65 peer_addr->bytes,
66 &del_param);
67 if (QDF_IS_STATUS_ERROR(qdf_status)) {
68 wma_err("Peer delete could not be sent to firmware %d",
69 qdf_status);
70 qdf_status = QDF_STATUS_E_FAILURE;
71 }
72
73 wma_remove_objmgr_peer(wma, wma->interfaces[vdev_id].vdev,
74 peer_addr->bytes);
75
76 return qdf_status;
77 }
78
79 QDF_STATUS
wma_pasn_peer_create(struct wlan_objmgr_psoc * psoc,struct qdf_mac_addr * peer_addr,uint8_t vdev_id)80 wma_pasn_peer_create(struct wlan_objmgr_psoc *psoc,
81 struct qdf_mac_addr *peer_addr,
82 uint8_t vdev_id)
83 {
84 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
85 target_resource_config *wlan_res_cfg;
86 struct wlan_objmgr_peer *obj_peer;
87 struct wma_target_req *wma_req;
88 struct peer_create_rsp_params *peer_create_rsp;
89 struct peer_create_params param;
90 QDF_STATUS status = QDF_STATUS_SUCCESS;
91 bool is_tgt_peer_conf_supported;
92
93 if (!wma) {
94 wma_err("wma_handle is NULL");
95 return QDF_STATUS_E_INVAL;
96 }
97
98 wlan_res_cfg = lmac_get_tgt_res_cfg(psoc);
99 if (!wlan_res_cfg) {
100 wma_err("psoc target res cfg is null");
101 return QDF_STATUS_E_INVAL;
102 }
103
104 if (wma->interfaces[vdev_id].peer_count >=
105 wlan_res_cfg->num_peers) {
106 wma_err("the peer count exceeds the limit %d",
107 wma->interfaces[vdev_id].peer_count);
108 return QDF_STATUS_E_FAILURE;
109 }
110
111 if (qdf_is_macaddr_group(peer_addr) ||
112 qdf_is_macaddr_zero(peer_addr)) {
113 wma_err("Invalid peer address received reject it");
114 return QDF_STATUS_E_FAILURE;
115 }
116
117 wma_acquire_wakelock(&wma->wmi_cmd_rsp_wake_lock,
118 WMA_PEER_CREATE_RESPONSE_TIMEOUT);
119 /*
120 * The peer object should be created before sending the WMI peer
121 * create command to firmware.
122 */
123 obj_peer = wma_create_objmgr_peer(wma, vdev_id, peer_addr->bytes,
124 WMI_PEER_TYPE_PASN, NULL);
125 if (!obj_peer) {
126 wma_release_wakelock(&wma->wmi_cmd_rsp_wake_lock);
127 return QDF_STATUS_E_FAILURE;
128 }
129
130 param.peer_addr = peer_addr->bytes;
131 param.peer_type = WMI_PEER_TYPE_PASN;
132 param.vdev_id = vdev_id;
133 if (wmi_unified_peer_create_send(wma->wmi_handle,
134 ¶m) != QDF_STATUS_SUCCESS) {
135 wma_err("Unable to create peer in Target");
136 wlan_objmgr_peer_obj_delete(obj_peer);
137 wma_release_wakelock(&wma->wmi_cmd_rsp_wake_lock);
138
139 return QDF_STATUS_E_FAILURE;
140 }
141
142 /*
143 * If fw doesn't advertise peer create confirm event support,
144 * use the legacy peer create API
145 */
146 is_tgt_peer_conf_supported =
147 wlan_psoc_nif_fw_ext_cap_get(wma->psoc,
148 WLAN_SOC_F_PEER_CREATE_RESP);
149 if (!is_tgt_peer_conf_supported) {
150 wma_release_wakelock(&wma->wmi_cmd_rsp_wake_lock);
151 return QDF_STATUS_SUCCESS;
152 }
153
154 peer_create_rsp = qdf_mem_malloc(sizeof(*peer_create_rsp));
155 if (!peer_create_rsp) {
156 wlan_objmgr_peer_obj_delete(obj_peer);
157 wma_release_wakelock(&wma->wmi_cmd_rsp_wake_lock);
158 return QDF_STATUS_E_NOMEM;
159 }
160
161 qdf_mem_copy(peer_create_rsp->peer_mac.bytes, peer_addr->bytes,
162 QDF_MAC_ADDR_SIZE);
163 wma_req = wma_fill_hold_req(wma, vdev_id, WMA_PEER_CREATE_REQ,
164 WMA_PASN_PEER_CREATE_RESPONSE,
165 peer_create_rsp,
166 WMA_PEER_CREATE_RESPONSE_TIMEOUT);
167 if (!wma_req) {
168 wma_err("vdev:%d failed to fill peer create req", vdev_id);
169 wma_remove_peer_req(wma, vdev_id, WMA_PASN_PEER_CREATE_RESPONSE,
170 peer_addr);
171 wma_pasn_peer_remove(psoc, peer_addr, vdev_id, false);
172 wma_release_wakelock(&wma->wmi_cmd_rsp_wake_lock);
173 qdf_mem_free(peer_create_rsp);
174 return QDF_STATUS_E_FAILURE;
175 }
176
177 wma_debug("Created ranging peer peer_addr " QDF_MAC_ADDR_FMT " vdev_id %d",
178 QDF_MAC_ADDR_REF(peer_addr->bytes), vdev_id);
179
180 return status;
181 }
182
183 QDF_STATUS
wma_pasn_handle_peer_create_conf(tp_wma_handle wma,struct qdf_mac_addr * peer_mac,QDF_STATUS status,uint8_t vdev_id)184 wma_pasn_handle_peer_create_conf(tp_wma_handle wma,
185 struct qdf_mac_addr *peer_mac,
186 QDF_STATUS status, uint8_t vdev_id)
187 {
188 struct wlan_lmac_if_wifi_pos_rx_ops *rx_ops;
189 struct wlan_objmgr_vdev *vdev;
190 enum QDF_OPMODE mode;
191
192 if (status)
193 wma_pasn_peer_remove(wma->psoc, peer_mac, vdev_id,
194 QDF_IS_STATUS_ERROR(status));
195
196 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(wma->psoc, vdev_id,
197 WLAN_LEGACY_WMA_ID);
198 if (!vdev) {
199 wma_err("Vdev is NULL");
200 return QDF_STATUS_E_NULL_VALUE;
201 }
202
203 mode = wlan_vdev_mlme_get_opmode(vdev);
204 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_WMA_ID);
205
206 /*
207 * Only in I-sta case update the wifi pos module to
208 * track the peer to initiate PASN authentication.
209 * For R-STA, return from here.
210 */
211 if (mode != QDF_STA_MODE) {
212 wma_debug("PASN opmode:%d is not sta", mode);
213 return QDF_STATUS_SUCCESS;
214 }
215
216 rx_ops = wifi_pos_get_rx_ops(wma->psoc);
217 if (!rx_ops || !rx_ops->wifi_pos_ranging_peer_create_rsp_cb) {
218 wma_err("%s is null",
219 !rx_ops ? "rx_ops" : "rx_ops->ranging_peer_cb");
220 return QDF_STATUS_E_NULL_VALUE;
221 }
222
223 rx_ops->wifi_pos_ranging_peer_create_rsp_cb(wma->psoc, vdev_id,
224 peer_mac, status);
225
226 return QDF_STATUS_SUCCESS;
227 }
228
229 QDF_STATUS
wma_resume_vdev_delete(tp_wma_handle wma,uint8_t vdev_id)230 wma_resume_vdev_delete(tp_wma_handle wma, uint8_t vdev_id)
231 {
232 struct wlan_objmgr_vdev *vdev;
233 struct mac_context *mac = wma->mac_context;
234
235 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(wma->psoc, vdev_id,
236 WLAN_LEGACY_WMA_ID);
237 if (!vdev) {
238 wma_err("Vdev is NULL");
239 return QDF_STATUS_E_NULL_VALUE;
240 }
241
242 lim_pasn_peer_del_all_resp_vdev_delete_resume(mac, vdev);
243
244 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_WMA_ID);
245
246 return QDF_STATUS_SUCCESS;
247 }
248
249 QDF_STATUS
wma_pasn_peer_delete_all_complete(struct wlan_objmgr_vdev * vdev)250 wma_pasn_peer_delete_all_complete(struct wlan_objmgr_vdev *vdev)
251 {
252 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
253 struct wma_target_req *req_msg;
254 uint8_t vdev_id = wlan_vdev_get_id(vdev);
255
256 if (!wma) {
257 wma_err("wma_handle is NULL");
258 return QDF_STATUS_E_FAILURE;
259 }
260
261 req_msg = wma_find_remove_req_msgtype(wma, vdev_id,
262 WMA_PASN_PEER_DELETE_REQUEST);
263 if (!req_msg) {
264 wma_debug("vdev:%d Failed to lookup pasn peer del req",
265 vdev_id);
266 return QDF_STATUS_E_FAILURE;
267 }
268
269 qdf_mc_timer_stop(&req_msg->event_timeout);
270 qdf_mc_timer_destroy(&req_msg->event_timeout);
271
272 qdf_mem_free(req_msg);
273
274 wma_release_wakelock(&wma->wmi_cmd_rsp_wake_lock);
275
276 return wma_resume_vdev_delete(wma, vdev_id);
277 }
278
279 QDF_STATUS
wma_delete_all_pasn_peers(tp_wma_handle wma,struct wlan_objmgr_vdev * vdev)280 wma_delete_all_pasn_peers(tp_wma_handle wma, struct wlan_objmgr_vdev *vdev)
281 {
282 struct wlan_lmac_if_wifi_pos_rx_ops *rx_ops;
283 struct wma_target_req *msg;
284 QDF_STATUS status = QDF_STATUS_SUCCESS;
285 uint8_t vdev_id = wlan_vdev_get_id(vdev);
286
287 rx_ops = wifi_pos_get_rx_ops(wma->psoc);
288 if (!rx_ops || !rx_ops->wifi_pos_vdev_delete_all_ranging_peers_cb) {
289 wma_err("rx_ops is NULL");
290 return QDF_STATUS_E_INVAL;
291 }
292
293 wma_acquire_wakelock(&wma->wmi_cmd_rsp_wake_lock,
294 WMA_PEER_DELETE_RESPONSE_TIMEOUT);
295 wma_err("Delete all ranging peers vdev:%d",
296 wlan_vdev_get_id(vdev));
297 status = rx_ops->wifi_pos_vdev_delete_all_ranging_peers_cb(vdev);
298 if (QDF_IS_STATUS_ERROR(status)) {
299 wma_release_wakelock(&wma->wmi_cmd_rsp_wake_lock);
300 wma_err("Delete all ranging peers failed");
301 return status;
302 }
303
304 msg = wma_fill_hold_req(wma, vdev_id,
305 WMA_PASN_PEER_DELETE_REQUEST,
306 WMA_PASN_PEER_DELETE_RESPONSE, NULL,
307 WMA_PEER_DELETE_RESPONSE_TIMEOUT);
308 if (!msg) {
309 wma_err("Failed to allocate request for vdev_id %d", vdev_id);
310 wma_remove_req(wma, vdev_id, WMA_PASN_PEER_DELETE_RESPONSE);
311 wma_release_wakelock(&wma->wmi_cmd_rsp_wake_lock);
312 wma_resume_vdev_delete(wma, vdev_id);
313 return QDF_STATUS_E_FAILURE;
314 }
315
316 return status;
317 }
318