1 /* 2 * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022 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: This file contains p2p south bound interface definitions 22 */ 23 24 #include <wlan_objmgr_psoc_obj.h> 25 #include <wlan_mgmt_txrx_utils_api.h> 26 #include <scheduler_api.h> 27 #include <wlan_objmgr_psoc_obj.h> 28 #include <wlan_objmgr_global_obj.h> 29 #include <wlan_objmgr_pdev_obj.h> 30 #include <wlan_objmgr_vdev_obj.h> 31 #include <wlan_objmgr_peer_obj.h> 32 #include "wlan_p2p_tgt_api.h" 33 #include "wlan_p2p_public_struct.h" 34 #include "../../core/src/wlan_p2p_main.h" 35 #include "../../core/src/wlan_p2p_roc.h" 36 #include "../../core/src/wlan_p2p_off_chan_tx.h" 37 38 #define IEEE80211_FC0_TYPE_MASK 0x0c 39 #define P2P_NOISE_FLOOR_DBM_DEFAULT (-96) 40 41 static inline struct wlan_lmac_if_p2p_tx_ops * wlan_psoc_get_p2p_tx_ops(struct wlan_objmgr_psoc * psoc)42 wlan_psoc_get_p2p_tx_ops(struct wlan_objmgr_psoc *psoc) 43 { 44 return &(psoc->soc_cb.tx_ops->p2p); 45 } 46 47 #ifdef FEATURE_P2P_LISTEN_OFFLOAD tgt_p2p_register_lo_ev_handler(struct wlan_objmgr_psoc * psoc)48 QDF_STATUS tgt_p2p_register_lo_ev_handler( 49 struct wlan_objmgr_psoc *psoc) 50 { 51 struct wlan_lmac_if_p2p_tx_ops *p2p_ops; 52 QDF_STATUS status = QDF_STATUS_E_FAILURE; 53 54 p2p_ops = wlan_psoc_get_p2p_tx_ops(psoc); 55 if (p2p_ops && p2p_ops->reg_lo_ev_handler) { 56 status = p2p_ops->reg_lo_ev_handler(psoc, NULL); 57 p2p_debug("register lo event, status:%d", status); 58 } 59 60 return status; 61 } 62 tgt_p2p_unregister_lo_ev_handler(struct wlan_objmgr_psoc * psoc)63 QDF_STATUS tgt_p2p_unregister_lo_ev_handler( 64 struct wlan_objmgr_psoc *psoc) 65 { 66 struct wlan_lmac_if_p2p_tx_ops *p2p_ops; 67 QDF_STATUS status = QDF_STATUS_E_FAILURE; 68 69 p2p_ops = wlan_psoc_get_p2p_tx_ops(psoc); 70 if (p2p_ops && p2p_ops->unreg_lo_ev_handler) { 71 status = p2p_ops->unreg_lo_ev_handler(psoc, NULL); 72 p2p_debug("unregister lo event, status:%d", status); 73 } 74 75 return status; 76 } 77 tgt_p2p_lo_event_cb(struct wlan_objmgr_psoc * psoc,struct p2p_lo_event * event_info)78 QDF_STATUS tgt_p2p_lo_event_cb(struct wlan_objmgr_psoc *psoc, 79 struct p2p_lo_event *event_info) 80 { 81 struct p2p_lo_stop_event *lo_stop_event; 82 struct scheduler_msg msg = {0}; 83 struct p2p_soc_priv_obj *p2p_soc_obj; 84 QDF_STATUS status; 85 86 p2p_debug("soc:%pK, event_info:%pK", psoc, event_info); 87 88 if (!psoc) { 89 p2p_err("psoc context passed is NULL"); 90 if (event_info) 91 qdf_mem_free(event_info); 92 return QDF_STATUS_E_INVAL; 93 } 94 95 p2p_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, 96 WLAN_UMAC_COMP_P2P); 97 if (!p2p_soc_obj) { 98 p2p_err("p2p soc object is NULL"); 99 if (event_info) 100 qdf_mem_free(event_info); 101 return QDF_STATUS_E_INVAL; 102 } 103 104 if (!event_info) { 105 p2p_err("invalid lo stop event information"); 106 return QDF_STATUS_E_INVAL; 107 } 108 109 lo_stop_event = qdf_mem_malloc(sizeof(*lo_stop_event)); 110 if (!lo_stop_event) { 111 qdf_mem_free(event_info); 112 return QDF_STATUS_E_NOMEM; 113 } 114 115 lo_stop_event->p2p_soc_obj = p2p_soc_obj; 116 lo_stop_event->lo_event = event_info; 117 msg.type = P2P_EVENT_LO_STOPPED; 118 msg.bodyptr = lo_stop_event; 119 msg.callback = p2p_process_evt; 120 msg.flush_callback = p2p_event_flush_callback; 121 status = scheduler_post_message(QDF_MODULE_ID_P2P, 122 QDF_MODULE_ID_P2P, 123 QDF_MODULE_ID_TARGET_IF, 124 &msg); 125 if (QDF_IS_STATUS_ERROR(status)) { 126 qdf_mem_free(lo_stop_event->lo_event); 127 qdf_mem_free(lo_stop_event); 128 p2p_err("post msg fail:%d", status); 129 } 130 131 return status; 132 } 133 #endif /* FEATURE_P2P_LISTEN_OFFLOAD */ 134 135 QDF_STATUS tgt_p2p_add_mac_addr_status_event_cb(struct wlan_objmgr_psoc * psoc,struct p2p_set_mac_filter_evt * event_info)136 tgt_p2p_add_mac_addr_status_event_cb(struct wlan_objmgr_psoc *psoc, 137 struct p2p_set_mac_filter_evt *event_info) 138 { 139 struct p2p_mac_filter_rsp *mac_filter_rsp; 140 struct scheduler_msg msg = {0}; 141 struct p2p_soc_priv_obj *p2p_soc_obj; 142 QDF_STATUS status; 143 144 if (!psoc) { 145 p2p_err("random_mac:psoc context passed is NULL"); 146 return QDF_STATUS_E_INVAL; 147 } 148 if (!event_info) { 149 p2p_err("random_mac:invalid event_info"); 150 return QDF_STATUS_E_INVAL; 151 } 152 153 p2p_soc_obj = wlan_objmgr_psoc_get_comp_private_obj( 154 psoc, WLAN_UMAC_COMP_P2P); 155 if (!p2p_soc_obj) { 156 p2p_err("random_mac:p2p soc object is NULL"); 157 return QDF_STATUS_E_INVAL; 158 } 159 160 mac_filter_rsp = qdf_mem_malloc(sizeof(*mac_filter_rsp)); 161 if (!mac_filter_rsp) 162 return QDF_STATUS_E_NOMEM; 163 164 mac_filter_rsp->p2p_soc_obj = p2p_soc_obj; 165 mac_filter_rsp->vdev_id = event_info->vdev_id; 166 mac_filter_rsp->status = event_info->status; 167 168 msg.type = P2P_EVENT_ADD_MAC_RSP; 169 msg.bodyptr = mac_filter_rsp; 170 msg.callback = p2p_process_evt; 171 status = scheduler_post_message(QDF_MODULE_ID_P2P, QDF_MODULE_ID_P2P, 172 QDF_MODULE_ID_TARGET_IF, &msg); 173 if (QDF_IS_STATUS_ERROR(status)) 174 qdf_mem_free(mac_filter_rsp); 175 176 return status; 177 } 178 tgt_p2p_register_macaddr_rx_filter_evt_handler(struct wlan_objmgr_psoc * psoc,bool reg)179 QDF_STATUS tgt_p2p_register_macaddr_rx_filter_evt_handler( 180 struct wlan_objmgr_psoc *psoc, bool reg) 181 { 182 struct wlan_lmac_if_p2p_tx_ops *p2p_ops; 183 QDF_STATUS status = QDF_STATUS_E_FAILURE; 184 185 p2p_ops = wlan_psoc_get_p2p_tx_ops(psoc); 186 if (p2p_ops && p2p_ops->reg_mac_addr_rx_filter_handler) { 187 status = p2p_ops->reg_mac_addr_rx_filter_handler(psoc, reg); 188 p2p_debug("register mac addr rx filter event, register %d status:%d", 189 reg, status); 190 } 191 192 return status; 193 } 194 tgt_p2p_register_noa_ev_handler(struct wlan_objmgr_psoc * psoc)195 QDF_STATUS tgt_p2p_register_noa_ev_handler( 196 struct wlan_objmgr_psoc *psoc) 197 { 198 struct wlan_lmac_if_p2p_tx_ops *p2p_ops; 199 QDF_STATUS status = QDF_STATUS_E_FAILURE; 200 201 p2p_ops = wlan_psoc_get_p2p_tx_ops(psoc); 202 if (p2p_ops && p2p_ops->reg_noa_ev_handler) { 203 status = p2p_ops->reg_noa_ev_handler(psoc, NULL); 204 p2p_debug("register noa event, status:%d", status); 205 } 206 207 return status; 208 } 209 tgt_p2p_unregister_noa_ev_handler(struct wlan_objmgr_psoc * psoc)210 QDF_STATUS tgt_p2p_unregister_noa_ev_handler( 211 struct wlan_objmgr_psoc *psoc) 212 { 213 struct wlan_lmac_if_p2p_tx_ops *p2p_ops; 214 QDF_STATUS status = QDF_STATUS_E_FAILURE; 215 216 p2p_ops = wlan_psoc_get_p2p_tx_ops(psoc); 217 if (p2p_ops && p2p_ops->unreg_noa_ev_handler) { 218 status = p2p_ops->unreg_noa_ev_handler(psoc, NULL); 219 p2p_debug("unregister noa event, status:%d", status); 220 } 221 222 return status; 223 } 224 tgt_p2p_scan_event_cb(struct wlan_objmgr_vdev * vdev,struct scan_event * event,void * arg)225 void tgt_p2p_scan_event_cb(struct wlan_objmgr_vdev *vdev, 226 struct scan_event *event, void *arg) 227 { 228 p2p_scan_event_cb(vdev, event, arg); 229 } 230 tgt_p2p_mgmt_download_comp_cb(void * context,qdf_nbuf_t buf,bool free)231 QDF_STATUS tgt_p2p_mgmt_download_comp_cb(void *context, 232 qdf_nbuf_t buf, bool free) 233 { 234 p2p_debug("context:%pK, buf:%pK, free:%d", context, 235 qdf_nbuf_data(buf), free); 236 237 qdf_nbuf_free(buf); 238 239 return QDF_STATUS_SUCCESS; 240 } 241 tgt_p2p_mgmt_ota_comp_cb(void * context,qdf_nbuf_t buf,uint32_t status,void * tx_compl_params)242 QDF_STATUS tgt_p2p_mgmt_ota_comp_cb(void *context, qdf_nbuf_t buf, 243 uint32_t status, void *tx_compl_params) 244 { 245 struct p2p_tx_conf_event *tx_conf_event; 246 struct scheduler_msg msg = {0}; 247 QDF_STATUS ret; 248 249 p2p_debug("context:%pK, buf:%pK, status:%d, tx complete params:%pK", 250 context, buf, status, tx_compl_params); 251 252 if (!context) { 253 p2p_err("invalid context"); 254 qdf_nbuf_free(buf); 255 return QDF_STATUS_E_INVAL; 256 } 257 258 tx_conf_event = qdf_mem_malloc(sizeof(*tx_conf_event)); 259 if (!tx_conf_event) { 260 qdf_nbuf_free(buf); 261 return QDF_STATUS_E_NOMEM; 262 } 263 264 tx_conf_event->status = status; 265 tx_conf_event->nbuf = buf; 266 tx_conf_event->p2p_soc_obj = (struct p2p_soc_priv_obj *)context; 267 msg.type = P2P_EVENT_MGMT_TX_ACK_CNF; 268 msg.bodyptr = tx_conf_event; 269 msg.callback = p2p_process_evt; 270 msg.flush_callback = p2p_event_flush_callback; 271 ret = scheduler_post_message(QDF_MODULE_ID_P2P, 272 QDF_MODULE_ID_P2P, 273 QDF_MODULE_ID_TARGET_IF, 274 &msg); 275 if (QDF_IS_STATUS_ERROR(ret)) { 276 qdf_mem_free(tx_conf_event); 277 qdf_nbuf_free(buf); 278 p2p_err("post msg fail:%d", status); 279 } 280 281 return ret; 282 } 283 tgt_p2p_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)284 QDF_STATUS tgt_p2p_mgmt_frame_rx_cb(struct wlan_objmgr_psoc *psoc, 285 struct wlan_objmgr_peer *peer, qdf_nbuf_t buf, 286 struct mgmt_rx_event_params *mgmt_rx_params, 287 enum mgmt_frame_type frm_type) 288 { 289 struct p2p_rx_mgmt_frame *rx_mgmt; 290 struct p2p_rx_mgmt_event *rx_mgmt_event; 291 struct p2p_soc_priv_obj *p2p_soc_obj; 292 struct scheduler_msg msg = {0}; 293 struct wlan_objmgr_vdev *vdev; 294 uint32_t vdev_id; 295 uint8_t *pdata; 296 QDF_STATUS status; 297 298 p2p_debug("psoc:%pK, peer:%pK, type:%d", psoc, peer, frm_type); 299 300 if (!mgmt_rx_params) { 301 p2p_err("mgmt rx params is NULL"); 302 qdf_nbuf_free(buf); 303 return QDF_STATUS_E_INVAL; 304 } 305 306 p2p_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, 307 WLAN_UMAC_COMP_P2P); 308 if (!p2p_soc_obj) { 309 p2p_err("p2p ctx is NULL, drop this frame"); 310 qdf_nbuf_free(buf); 311 return QDF_STATUS_E_FAILURE; 312 } 313 314 if (!peer) { 315 if (p2p_soc_obj->cur_roc_vdev_id == P2P_INVALID_VDEV_ID) { 316 p2p_debug("vdev id of current roc invalid"); 317 qdf_nbuf_free(buf); 318 return QDF_STATUS_E_FAILURE; 319 } else { 320 vdev_id = p2p_soc_obj->cur_roc_vdev_id; 321 } 322 } else { 323 vdev = wlan_peer_get_vdev(peer); 324 if (!vdev) { 325 p2p_err("vdev is NULL in peer, drop this frame"); 326 qdf_nbuf_free(buf); 327 return QDF_STATUS_E_FAILURE; 328 } 329 vdev_id = wlan_vdev_get_id(vdev); 330 } 331 332 rx_mgmt_event = qdf_mem_malloc_atomic(sizeof(*rx_mgmt_event)); 333 if (!rx_mgmt_event) { 334 p2p_debug_rl("Failed to allocate rx mgmt event"); 335 qdf_nbuf_free(buf); 336 return QDF_STATUS_E_NOMEM; 337 } 338 339 rx_mgmt = qdf_mem_malloc_atomic(sizeof(*rx_mgmt) + 340 mgmt_rx_params->buf_len); 341 if (!rx_mgmt) { 342 p2p_debug_rl("Failed to allocate rx mgmt frame"); 343 qdf_nbuf_free(buf); 344 return QDF_STATUS_E_NOMEM; 345 } 346 347 pdata = (uint8_t *)qdf_nbuf_data(buf); 348 rx_mgmt->frame_len = mgmt_rx_params->buf_len; 349 rx_mgmt->rx_freq = mgmt_rx_params->chan_freq; 350 rx_mgmt->vdev_id = vdev_id; 351 rx_mgmt->frm_type = frm_type; 352 rx_mgmt->rx_rssi = mgmt_rx_params->snr + 353 P2P_NOISE_FLOOR_DBM_DEFAULT; 354 rx_mgmt_event->rx_mgmt = rx_mgmt; 355 rx_mgmt_event->p2p_soc_obj = p2p_soc_obj; 356 qdf_mem_copy(rx_mgmt->buf, pdata, mgmt_rx_params->buf_len); 357 msg.type = P2P_EVENT_RX_MGMT; 358 msg.bodyptr = rx_mgmt_event; 359 msg.callback = p2p_process_evt; 360 msg.flush_callback = p2p_event_flush_callback; 361 status = scheduler_post_message(QDF_MODULE_ID_P2P, 362 QDF_MODULE_ID_P2P, 363 QDF_MODULE_ID_TARGET_IF, 364 &msg); 365 if (QDF_IS_STATUS_ERROR(status)) { 366 qdf_mem_free(rx_mgmt_event->rx_mgmt); 367 qdf_mem_free(rx_mgmt_event); 368 p2p_err("post msg fail:%d", status); 369 } 370 qdf_nbuf_free(buf); 371 372 return status; 373 } 374 tgt_p2p_noa_event_cb(struct wlan_objmgr_psoc * psoc,struct p2p_noa_info * event_info)375 QDF_STATUS tgt_p2p_noa_event_cb(struct wlan_objmgr_psoc *psoc, 376 struct p2p_noa_info *event_info) 377 { 378 struct p2p_noa_event *noa_event; 379 struct scheduler_msg msg = {0}; 380 struct p2p_soc_priv_obj *p2p_soc_obj; 381 QDF_STATUS status; 382 383 p2p_debug("soc:%pK, event_info:%pK", psoc, event_info); 384 385 if (!psoc) { 386 p2p_err("psoc context passed is NULL"); 387 if (event_info) 388 qdf_mem_free(event_info); 389 return QDF_STATUS_E_INVAL; 390 } 391 392 p2p_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, 393 WLAN_UMAC_COMP_P2P); 394 if (!p2p_soc_obj) { 395 p2p_err("p2p soc object is NULL"); 396 if (event_info) 397 qdf_mem_free(event_info); 398 return QDF_STATUS_E_INVAL; 399 } 400 401 if (!event_info) { 402 p2p_err("invalid noa event information"); 403 return QDF_STATUS_E_INVAL; 404 } 405 406 noa_event = qdf_mem_malloc(sizeof(*noa_event)); 407 if (!noa_event) { 408 qdf_mem_free(event_info); 409 return QDF_STATUS_E_NOMEM; 410 } 411 412 noa_event->p2p_soc_obj = p2p_soc_obj; 413 noa_event->noa_info = event_info; 414 msg.type = P2P_EVENT_NOA; 415 msg.bodyptr = noa_event; 416 msg.callback = p2p_process_evt; 417 msg.flush_callback = p2p_event_flush_callback; 418 status = scheduler_post_message(QDF_MODULE_ID_P2P, 419 QDF_MODULE_ID_P2P, 420 QDF_MODULE_ID_TARGET_IF, 421 &msg); 422 if (QDF_IS_STATUS_ERROR(status)) { 423 qdf_mem_free(noa_event->noa_info); 424 qdf_mem_free(noa_event); 425 p2p_err("post msg fail:%d", status); 426 } 427 428 return status; 429 } 430