| /* |
| * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved. |
| * |
| * Previously licensed under the ISC license by Qualcomm Atheros, Inc. |
| * |
| * Permission to use, copy, modify, and/or distribute this software for |
| * any purpose with or without fee is hereby granted, provided that the |
| * above copyright notice and this permission notice appear in all |
| * copies. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL |
| * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE |
| * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL |
| * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR |
| * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
| * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
| * PERFORMANCE OF THIS SOFTWARE. |
| */ |
| |
| /** |
| * DOC: wma_nan_datapath.c |
| * |
| * WMA NAN Data path API implementation |
| */ |
| |
| #include "wma.h" |
| #include "wma_api.h" |
| #include "vos_api.h" |
| #include "wmi_unified_api.h" |
| #include "wmi_unified.h" |
| #include "wma_nan_datapath.h" |
| |
| /** |
| * wma_handle_ndp_initiator_req() - NDP initiator request handler |
| * @wma_handle: wma handle |
| * @req: request parameters |
| * |
| * Return: VOS_STATUS_SUCCESS on success; error number otherwise |
| */ |
| VOS_STATUS wma_handle_ndp_initiator_req(tp_wma_handle wma_handle, void *req) |
| { |
| VOS_STATUS status; |
| int ret; |
| uint16_t len; |
| uint32_t vdev_id, ndp_cfg_len, ndp_app_info_len, pmk_len; |
| struct ndp_initiator_rsp *rsp = NULL; |
| ol_txrx_vdev_handle vdev; |
| wmi_buf_t buf; |
| wmi_ndp_initiator_req_fixed_param *cmd; |
| vos_msg_t pe_msg = {0}; |
| struct ndp_initiator_req *ndp_req = req; |
| wmi_channel *ch_tlv; |
| uint8_t *tlv_ptr; |
| |
| if (NULL == ndp_req) { |
| WMA_LOGE(FL("Invalid ndp_req.")); |
| goto send_ndp_initiator_fail; |
| } |
| vdev_id = ndp_req->vdev_id; |
| vdev = wma_find_vdev_by_id(wma_handle, vdev_id); |
| if (!vdev) { |
| WMA_LOGE(FL("vdev not found for vdev id %d."), vdev_id); |
| goto send_ndp_initiator_fail; |
| } |
| |
| if (!WMA_IS_VDEV_IN_NDI_MODE(wma_handle->interfaces, vdev_id)) { |
| WMA_LOGE(FL("vdev :%d, not in NDI mode"), vdev_id); |
| goto send_ndp_initiator_fail; |
| } |
| |
| /* |
| * WMI command expects 4 byte alligned len: |
| * round up ndp_cfg_len and ndp_app_info_len to 4 bytes |
| */ |
| ndp_cfg_len = vos_roundup(ndp_req->ndp_config.ndp_cfg_len, 4); |
| ndp_app_info_len = vos_roundup(ndp_req->ndp_info.ndp_app_info_len, 4); |
| pmk_len = vos_roundup(ndp_req->pmk.pmk_len, 4); |
| /* allocated memory for fixed params as well as variable size data */ |
| len = sizeof(*cmd) + sizeof(*ch_tlv) + (3 * WMI_TLV_HDR_SIZE) |
| + ndp_cfg_len + ndp_app_info_len + pmk_len; |
| |
| buf = wmi_buf_alloc(wma_handle->wmi_handle, len); |
| if (!buf) { |
| WMA_LOGE(FL("wmi_buf_alloc failed")); |
| goto send_ndp_initiator_fail; |
| } |
| cmd = (wmi_ndp_initiator_req_fixed_param *) wmi_buf_data(buf); |
| WMITLV_SET_HDR(&cmd->tlv_header, |
| WMITLV_TAG_STRUC_wmi_ndp_initiator_req_fixed_param, |
| WMITLV_GET_STRUCT_TLVLEN( |
| wmi_ndp_initiator_req_fixed_param)); |
| cmd->vdev_id = ndp_req->vdev_id; |
| cmd->transaction_id = ndp_req->transaction_id; |
| cmd->service_instance_id = ndp_req->service_instance_id; |
| WMI_CHAR_ARRAY_TO_MAC_ADDR(ndp_req->peer_discovery_mac_addr.bytes, |
| &cmd->peer_discovery_mac_addr); |
| |
| cmd->ndp_cfg_len = ndp_req->ndp_config.ndp_cfg_len; |
| cmd->ndp_app_info_len = ndp_req->ndp_info.ndp_app_info_len; |
| cmd->ndp_channel_cfg = ndp_req->channel_cfg; |
| cmd->nan_pmk_len = ndp_req->pmk.pmk_len; |
| cmd->nan_csid = ndp_req->ncs_sk_type; |
| |
| ch_tlv = (wmi_channel *)&cmd[1]; |
| WMITLV_SET_HDR(ch_tlv, WMITLV_TAG_STRUC_wmi_channel, |
| WMITLV_GET_STRUCT_TLVLEN(wmi_channel)); |
| ch_tlv->mhz = ndp_req->channel; |
| ch_tlv->band_center_freq1 = |
| vos_chan_to_freq(vos_freq_to_chan(ndp_req->channel)); |
| tlv_ptr = (uint8_t *)&ch_tlv[1]; |
| |
| WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, ndp_cfg_len); |
| vos_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE], |
| ndp_req->ndp_config.ndp_cfg, cmd->ndp_cfg_len); |
| tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + ndp_cfg_len; |
| |
| WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, ndp_app_info_len); |
| vos_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE], |
| ndp_req->ndp_info.ndp_app_info, cmd->ndp_app_info_len); |
| tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + ndp_app_info_len; |
| |
| WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, pmk_len); |
| vos_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE], ndp_req->pmk.pmk, |
| cmd->nan_pmk_len); |
| tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + pmk_len; |
| |
| WMA_LOGE(FL("vdev_id = %d, transaction_id: %d, service_instance_id: %d, ch: %d, ch_cfg: %d, csid: %d"), |
| cmd->vdev_id, cmd->transaction_id, cmd->service_instance_id, |
| ch_tlv->mhz, cmd->ndp_channel_cfg, cmd->nan_csid); |
| WMA_LOGE(FL("peer mac addr: mac_addr31to0: 0x%x, mac_addr47to32: 0x%x"), |
| cmd->peer_discovery_mac_addr.mac_addr31to0, |
| cmd->peer_discovery_mac_addr.mac_addr47to32); |
| |
| WMA_LOGE(FL("ndp_config len: %d"), cmd->ndp_cfg_len); |
| VOS_TRACE_HEX_DUMP(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_DEBUG, |
| ndp_req->ndp_config.ndp_cfg, |
| ndp_req->ndp_config.ndp_cfg_len); |
| |
| WMA_LOGE(FL("ndp_app_info len: %d"), cmd->ndp_app_info_len); |
| VOS_TRACE_HEX_DUMP(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_DEBUG, |
| ndp_req->ndp_info.ndp_app_info, |
| ndp_req->ndp_info.ndp_app_info_len); |
| |
| WMA_LOGE(FL("pmk len: %d"), cmd->nan_pmk_len); |
| VOS_TRACE_HEX_DUMP(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_DEBUG, |
| ndp_req->pmk.pmk, cmd->nan_pmk_len); |
| WMA_LOGE(FL("sending WMI_NDP_INITIATOR_REQ_CMDID(0x%X)"), |
| WMI_NDP_INITIATOR_REQ_CMDID); |
| |
| ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, |
| WMI_NDP_INITIATOR_REQ_CMDID); |
| if (ret < 0) { |
| WMA_LOGE(FL("WMI_NDP_INITIATOR_REQ_CMDID failed, ret: %d"), |
| ret); |
| wmi_buf_free(buf); |
| goto send_ndp_initiator_fail; |
| } |
| |
| return VOS_STATUS_SUCCESS; |
| |
| send_ndp_initiator_fail: |
| status = VOS_STATUS_E_FAILURE; |
| if (ndp_req) { |
| rsp = vos_mem_malloc(sizeof(*rsp)); |
| if (NULL == rsp) { |
| WMA_LOGE(FL("Memory allocation failure")); |
| status = VOS_STATUS_E_NOMEM; |
| /* unblock SME queue, but do not send rsp to HDD */ |
| pe_msg.bodyval = true; |
| } else { |
| rsp->vdev_id = ndp_req->vdev_id; |
| rsp->transaction_id = ndp_req->transaction_id; |
| rsp->ndp_instance_id = ndp_req->service_instance_id; |
| rsp->status = NDP_RSP_STATUS_ERROR; |
| rsp->reason = NDP_DATA_INITIATOR_REQ_FAILED; |
| } |
| } else { |
| /* unblock SME queue, but do not send rsp to HDD */ |
| pe_msg.bodyval = true; |
| } |
| |
| pe_msg.type = SIR_HAL_NDP_INITIATOR_RSP; |
| pe_msg.bodyptr = rsp; |
| |
| if (VOS_STATUS_SUCCESS != |
| vos_mq_post_message(VOS_MODULE_ID_PE, &pe_msg)) { |
| WMA_LOGE("SIR_HAL_NDP_INITIATOR_RSP to PE failed"); |
| vos_mem_free(rsp); |
| } |
| |
| return status; |
| } |
| |
| /** |
| * wma_send_ndp_responder_rsp() - NDP responder request handler |
| * @rsp_ind: rsp parameters |
| * |
| * Return: VOS_STATUS_SUCCESS on success; error number otherwise |
| */ |
| static VOS_STATUS wma_send_ndp_responder_rsp |
| (struct ndp_responder_rsp_event *rsp_ind) |
| { |
| VOS_STATUS status; |
| vos_msg_t pe_msg = {0}; |
| uint8_t len = sizeof(*rsp_ind); |
| |
| if (NULL == rsp_ind) { |
| WMA_LOGE(FL("Invalid rsp_ind")); |
| /* msg to unblock SME, but not send rsp to HDD */ |
| pe_msg.bodyptr = NULL; |
| pe_msg.bodyval = true; |
| goto send_rsp; |
| } |
| pe_msg.bodyptr = vos_mem_malloc(len); |
| if (NULL == pe_msg.bodyptr) { |
| WMA_LOGE(FL("Memory allocation failure")); |
| /* msg to unblock SME, but not send rsp to HDD */ |
| pe_msg.bodyval = true; |
| } else { |
| vos_mem_copy(pe_msg.bodyptr, rsp_ind, len); |
| pe_msg.bodyval = 0; |
| } |
| send_rsp: |
| pe_msg.type = SIR_HAL_NDP_RESPONDER_RSP; |
| status = vos_mq_post_message(VOS_MODULE_ID_PE, &pe_msg); |
| if (!VOS_IS_STATUS_SUCCESS(status)) { |
| WMA_LOGE(FL("fail to post msg to PE")); |
| vos_mem_free(pe_msg.bodyptr); |
| } |
| return status; |
| } |
| |
| /** |
| * wma_handle_ndp_responder_req() - NDP responder request handler |
| * @wma_handle: wma handle |
| * @req_params: request parameters |
| * |
| * Return: VOS_STATUS_SUCCESS on success; error number otherwise |
| */ |
| VOS_STATUS wma_handle_ndp_responder_req(tp_wma_handle wma_handle, |
| struct ndp_responder_req *req_params) |
| { |
| wmi_buf_t buf; |
| ol_txrx_vdev_handle vdev; |
| uint32_t vdev_id = 0, ndp_cfg_len, ndp_app_info_len, pmk_len; |
| uint8_t *tlv_ptr; |
| int ret; |
| wmi_ndp_responder_req_fixed_param *cmd; |
| uint16_t len; |
| struct ndp_responder_rsp_event rsp; |
| |
| if (NULL == req_params) { |
| WMA_LOGE(FL("Invalid req_params.")); |
| return VOS_STATUS_E_INVAL; |
| } |
| |
| vdev_id = req_params->vdev_id; |
| WMA_LOGD(FL("vdev_id: %d, transaction_id: %d, ndp_rsp %d, ndp_instance_id: %d, ndp_app_info_len: %d"), |
| req_params->vdev_id, req_params->transaction_id, |
| req_params->ndp_rsp, |
| req_params->ndp_instance_id, |
| req_params->ndp_info.ndp_app_info_len); |
| vdev = wma_find_vdev_by_id(wma_handle, vdev_id); |
| if (!vdev) { |
| WMA_LOGE(FL("vdev not found for vdev id %d."), vdev_id); |
| goto send_ndp_responder_fail; |
| } |
| |
| if (!WMA_IS_VDEV_IN_NDI_MODE(wma_handle->interfaces, vdev_id)) { |
| WMA_LOGE(FL("vdev :$%d, not in NDI mode"), vdev_id); |
| goto send_ndp_responder_fail; |
| } |
| |
| /* |
| * WMI command expects 4 byte alligned len: |
| * round up ndp_cfg_len and ndp_app_info_len to 4 bytes |
| */ |
| ndp_cfg_len = vos_roundup(req_params->ndp_config.ndp_cfg_len, 4); |
| ndp_app_info_len = vos_roundup(req_params->ndp_info.ndp_app_info_len, 4); |
| pmk_len = vos_roundup(req_params->pmk.pmk_len, 4); |
| /* allocated memory for fixed params as well as variable size data */ |
| len = sizeof(*cmd) + 3*WMI_TLV_HDR_SIZE + ndp_cfg_len + ndp_app_info_len |
| + pmk_len; |
| |
| buf = wmi_buf_alloc(wma_handle->wmi_handle, len); |
| if (!buf) { |
| WMA_LOGE(FL("wmi_buf_alloc failed")); |
| goto send_ndp_responder_fail; |
| } |
| cmd = (wmi_ndp_responder_req_fixed_param *) wmi_buf_data(buf); |
| WMITLV_SET_HDR(&cmd->tlv_header, |
| WMITLV_TAG_STRUC_wmi_ndp_responder_req_fixed_param, |
| WMITLV_GET_STRUCT_TLVLEN( |
| wmi_ndp_responder_req_fixed_param)); |
| cmd->vdev_id = req_params->vdev_id; |
| cmd->transaction_id = req_params->transaction_id; |
| cmd->ndp_instance_id = req_params->ndp_instance_id; |
| cmd->rsp_code = req_params->ndp_rsp; |
| |
| cmd->ndp_cfg_len = req_params->ndp_config.ndp_cfg_len; |
| cmd->ndp_app_info_len = req_params->ndp_info.ndp_app_info_len; |
| cmd->nan_pmk_len = req_params->pmk.pmk_len; |
| cmd->nan_csid = req_params->ncs_sk_type; |
| |
| tlv_ptr = (uint8_t *)&cmd[1]; |
| |
| WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, ndp_cfg_len); |
| vos_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE], |
| req_params->ndp_config.ndp_cfg, cmd->ndp_cfg_len); |
| tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + ndp_cfg_len; |
| |
| WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, ndp_app_info_len); |
| vos_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE], |
| req_params->ndp_info.ndp_app_info, |
| req_params->ndp_info.ndp_app_info_len); |
| tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + ndp_app_info_len; |
| |
| WMITLV_SET_HDR(tlv_ptr, WMITLV_TAG_ARRAY_BYTE, pmk_len); |
| vos_mem_copy(&tlv_ptr[WMI_TLV_HDR_SIZE], req_params->pmk.pmk, |
| cmd->nan_pmk_len); |
| tlv_ptr = tlv_ptr + WMI_TLV_HDR_SIZE + pmk_len; |
| |
| WMA_LOGE(FL("vdev_id = %d, transaction_id: %d, csid: %d"), |
| cmd->vdev_id, cmd->transaction_id, cmd->nan_csid); |
| |
| WMA_LOGD(FL("ndp_config len: %d"), |
| req_params->ndp_config.ndp_cfg_len); |
| VOS_TRACE_HEX_DUMP(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_DEBUG, |
| req_params->ndp_config.ndp_cfg, |
| req_params->ndp_config.ndp_cfg_len); |
| |
| WMA_LOGD(FL("ndp_app_info len: %d"), |
| req_params->ndp_info.ndp_app_info_len); |
| VOS_TRACE_HEX_DUMP(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_DEBUG, |
| req_params->ndp_info.ndp_app_info, |
| req_params->ndp_info.ndp_app_info_len); |
| |
| WMA_LOGE(FL("pmk len: %d"), cmd->nan_pmk_len); |
| VOS_TRACE_HEX_DUMP(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_DEBUG, |
| req_params->pmk.pmk, cmd->nan_pmk_len); |
| |
| WMA_LOGE(FL("sending WMI_NDP_RESPONDER_REQ_CMDID(0x%X)"), |
| WMI_NDP_RESPONDER_REQ_CMDID); |
| ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, |
| WMI_NDP_RESPONDER_REQ_CMDID); |
| if (ret < 0) { |
| WMA_LOGE(FL("WMI_NDP_RESPONDER_REQ_CMDID failed, ret: %d"), |
| ret); |
| wmi_buf_free(buf); |
| goto send_ndp_responder_fail; |
| } |
| return VOS_STATUS_SUCCESS; |
| send_ndp_responder_fail: |
| vos_mem_zero(&rsp, sizeof(rsp)); |
| rsp.vdev_id = req_params->vdev_id; |
| rsp.transaction_id = req_params->transaction_id; |
| rsp.status = NDP_RSP_STATUS_ERROR; |
| rsp.reason = NDP_DATA_RESPONDER_REQ_FAILED; |
| wma_send_ndp_responder_rsp(&rsp); |
| return VOS_STATUS_E_FAILURE; |
| } |
| |
| /** |
| * wma_handle_ndp_end_req() - NDP end request handler |
| * @wma_handle: wma handle |
| * @ptr: request parameters |
| * |
| * Return: VOS_STATUS_SUCCESS on success; error number otherwise |
| */ |
| VOS_STATUS wma_handle_ndp_end_req(tp_wma_handle wma_handle, void *ptr) |
| { |
| int ret; |
| uint16_t len; |
| uint32_t ndp_end_req_len, i; |
| wmi_ndp_end_req *ndp_end_req_lst; |
| wmi_buf_t buf; |
| vos_msg_t pe_msg = {0}; |
| wmi_ndp_end_req_fixed_param *cmd; |
| struct ndp_end_rsp_event *end_rsp = NULL; |
| struct ndp_end_req *req = ptr; |
| |
| if (NULL == req) { |
| WMA_LOGE(FL("Invalid ndp_end_req")); |
| goto send_ndp_end_fail; |
| } |
| |
| /* len of tlv following fixed param */ |
| ndp_end_req_len = sizeof(wmi_ndp_end_req) * req->num_ndp_instances; |
| /* above comes out to 4 byte alligned already, no need of padding */ |
| len = sizeof(*cmd) + ndp_end_req_len + WMI_TLV_HDR_SIZE; |
| buf = wmi_buf_alloc(wma_handle->wmi_handle, len); |
| if (!buf) { |
| WMA_LOGE(FL("Malloc failed")); |
| return VOS_STATUS_E_NOMEM; |
| } |
| cmd = (wmi_ndp_end_req_fixed_param *) wmi_buf_data(buf); |
| |
| WMITLV_SET_HDR(&cmd->tlv_header, |
| WMITLV_TAG_STRUC_wmi_ndp_end_req_fixed_param, |
| WMITLV_GET_STRUCT_TLVLEN(wmi_ndp_end_req_fixed_param)); |
| |
| cmd->transaction_id = req->transaction_id; |
| |
| /* set tlv pointer to end of fixed param */ |
| WMITLV_SET_HDR((uint8_t *)&cmd[1], WMITLV_TAG_ARRAY_STRUC, |
| ndp_end_req_len); |
| |
| ndp_end_req_lst = (wmi_ndp_end_req *)((uint8_t *)&cmd[1] + |
| WMI_TLV_HDR_SIZE); |
| for (i = 0; i < req->num_ndp_instances; i++) { |
| WMITLV_SET_HDR(&ndp_end_req_lst[i], |
| WMITLV_TAG_ARRAY_FIXED_STRUC, |
| (sizeof(*ndp_end_req_lst) - WMI_TLV_HDR_SIZE)); |
| |
| ndp_end_req_lst[i].ndp_instance_id = req->ndp_ids[i]; |
| } |
| |
| WMA_LOGD(FL("Sending WMI_NDP_END_REQ_CMDID to FW")); |
| ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, |
| WMI_NDP_END_REQ_CMDID); |
| if (ret < 0) { |
| WMA_LOGE(FL("WMI_NDP_END_REQ_CMDID failed, ret: %d"), ret); |
| wmi_buf_free(buf); |
| goto send_ndp_end_fail; |
| } |
| return VOS_STATUS_SUCCESS; |
| |
| send_ndp_end_fail: |
| pe_msg.type = SIR_HAL_NDP_END_RSP; |
| if (req) { |
| end_rsp = vos_mem_malloc(sizeof(*end_rsp)); |
| if (NULL == end_rsp) { |
| WMA_LOGE(FL("Malloc failed")); |
| pe_msg.bodyval = true; |
| } else { |
| vos_mem_zero(end_rsp, sizeof(*end_rsp)); |
| end_rsp->status = NDP_RSP_STATUS_ERROR; |
| end_rsp->reason = NDP_END_FAILED; |
| end_rsp->transaction_id = req->transaction_id; |
| pe_msg.bodyptr = end_rsp; |
| } |
| } else { |
| pe_msg.bodyval = true; |
| } |
| |
| if (VOS_STATUS_SUCCESS != |
| vos_mq_post_message(VOS_MODULE_ID_PE, &pe_msg)) { |
| WMA_LOGE("NDP_END_RSP to PE failed"); |
| vos_mem_free(end_rsp); |
| } |
| return VOS_STATUS_E_FAILURE; |
| } |
| |
| /** |
| * wma_handle_ndp_sched_update_req() - NDP schedule update request handler |
| * @wma_handle: wma handle |
| * @req_params: request parameters |
| * |
| * Return: VOS_STATUS_SUCCESS on success; error number otherwise |
| */ |
| VOS_STATUS wma_handle_ndp_sched_update_req(tp_wma_handle wma_handle, |
| struct ndp_end_req *req_params) |
| { |
| return VOS_STATUS_SUCCESS; |
| } |
| |
| /** |
| * wma_ndp_indication_event_handler() - NDP indication event handler |
| * @handle: wma handle |
| * @event_info: event handler data |
| * @len: length of event_info |
| * |
| * Handler for WMI_NDP_INDICATION_EVENTID |
| * Return: 0 on success, negative errno on failure |
| */ |
| static int wma_ndp_indication_event_handler(void *handle, uint8_t *event_info, |
| uint32_t len) |
| { |
| WMI_NDP_INDICATION_EVENTID_param_tlvs *event; |
| wmi_ndp_indication_event_fixed_param *fixed_params; |
| vos_msg_t pe_msg = {0}; |
| struct ndp_indication_event *ind_event; |
| VOS_STATUS status; |
| |
| event = (WMI_NDP_INDICATION_EVENTID_param_tlvs *)event_info; |
| fixed_params = |
| (wmi_ndp_indication_event_fixed_param *)event->fixed_param; |
| |
| ind_event = vos_mem_malloc(sizeof(*ind_event)); |
| if (!ind_event) { |
| WMA_LOGP(FL("Failed to allocate memory")); |
| return VOS_STATUS_E_NOMEM; |
| } |
| vos_mem_zero(ind_event, sizeof(*ind_event)); |
| ind_event->vdev_id = fixed_params->vdev_id; |
| ind_event->service_instance_id = fixed_params->service_instance_id; |
| ind_event->ndp_instance_id = fixed_params->ndp_instance_id; |
| ind_event->role = fixed_params->self_ndp_role; |
| ind_event->policy = fixed_params->accept_policy; |
| |
| WMI_MAC_ADDR_TO_CHAR_ARRAY(&fixed_params->peer_ndi_mac_addr, |
| ind_event->peer_mac_addr.bytes); |
| WMI_MAC_ADDR_TO_CHAR_ARRAY(&fixed_params->peer_discovery_mac_addr, |
| ind_event->peer_discovery_mac_addr.bytes); |
| |
| WMA_LOGD(FL("WMI_NDP_INDICATION_EVENTID(0x%X) received. vdev %d, \n" |
| "service_instance %d, ndp_instance %d, role %d, policy %d, \n" |
| "csid: %d, scid_len: %d, peer_mac_addr: %pM, peer_disc_mac_addr: %pM"), |
| WMI_NDP_INDICATION_EVENTID, fixed_params->vdev_id, |
| fixed_params->service_instance_id, |
| fixed_params->ndp_instance_id, fixed_params->self_ndp_role, |
| fixed_params->accept_policy, |
| fixed_params->nan_csid, fixed_params->nan_scid_len, |
| ind_event->peer_mac_addr.bytes, |
| ind_event->peer_discovery_mac_addr.bytes); |
| |
| WMA_LOGD(FL("ndp_cfg - %d bytes"), fixed_params->ndp_cfg_len); |
| VOS_TRACE_HEX_DUMP(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_DEBUG, |
| &event->ndp_cfg, fixed_params->ndp_cfg_len); |
| |
| WMA_LOGD(FL("ndp_app_info - %d bytes"), fixed_params->ndp_app_info_len); |
| VOS_TRACE_HEX_DUMP(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_DEBUG, |
| &event->ndp_app_info, fixed_params->ndp_app_info_len); |
| ind_event->ndp_config.ndp_cfg_len = fixed_params->ndp_cfg_len; |
| ind_event->ndp_info.ndp_app_info_len = fixed_params->ndp_app_info_len; |
| ind_event->ncs_sk_type = fixed_params->nan_csid; |
| ind_event->scid.scid_len = fixed_params->nan_scid_len; |
| |
| if (ind_event->ndp_config.ndp_cfg_len) { |
| ind_event->ndp_config.ndp_cfg = |
| vos_mem_malloc(fixed_params->ndp_cfg_len); |
| if (NULL == ind_event->ndp_config.ndp_cfg) { |
| WMA_LOGE(FL("malloc failed")); |
| vos_mem_free(ind_event); |
| return VOS_STATUS_E_NOMEM; |
| } |
| vos_mem_copy(ind_event->ndp_config.ndp_cfg, event->ndp_cfg, |
| ind_event->ndp_config.ndp_cfg_len); |
| } |
| |
| if (ind_event->ndp_info.ndp_app_info_len) { |
| ind_event->ndp_info.ndp_app_info = |
| vos_mem_malloc(ind_event->ndp_info.ndp_app_info_len); |
| if (NULL == ind_event->ndp_info.ndp_app_info) { |
| WMA_LOGE(FL("malloc failed")); |
| vos_mem_free(ind_event->ndp_config.ndp_cfg); |
| vos_mem_free(ind_event); |
| return VOS_STATUS_E_NOMEM; |
| } |
| vos_mem_copy(ind_event->ndp_info.ndp_app_info, |
| event->ndp_app_info, |
| ind_event->ndp_info.ndp_app_info_len); |
| } |
| |
| if (ind_event->scid.scid_len) { |
| ind_event->scid.scid = |
| vos_mem_malloc(ind_event->scid.scid_len); |
| if (NULL == ind_event->scid.scid) { |
| WMA_LOGE(FL("malloc failed")); |
| vos_mem_free(ind_event->ndp_config.ndp_cfg); |
| vos_mem_free(ind_event->ndp_info.ndp_app_info); |
| vos_mem_free(ind_event); |
| return VOS_STATUS_E_NOMEM; |
| } |
| vos_mem_copy(ind_event->scid.scid, |
| event->ndp_scid, ind_event->scid.scid_len); |
| WMA_LOGD(FL("scid hex dump:")); |
| VOS_TRACE_HEX_DUMP(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_DEBUG, |
| ind_event->scid.scid, ind_event->scid.scid_len); |
| } |
| |
| pe_msg.type = SIR_HAL_NDP_INDICATION; |
| pe_msg.bodyptr = ind_event; |
| pe_msg.bodyval = 0; |
| |
| WMA_LOGE(FL("Sending SIR_HAL_NDP_INDICATION msg to PE")); |
| status = vos_mq_post_message(VOS_MODULE_ID_PE, &pe_msg); |
| if (!VOS_IS_STATUS_SUCCESS(status)) { |
| WMA_LOGE(FL("fail to post SIR_HAL_NDP_INDICATION msg to PE")); |
| vos_mem_free(ind_event->ndp_config.ndp_cfg); |
| vos_mem_free(ind_event->ndp_info.ndp_app_info); |
| vos_mem_free(ind_event->scid.scid); |
| vos_mem_free(ind_event); |
| } |
| |
| return status; |
| } |
| |
| /** |
| * wma_ndp_responder_rsp_event_handler() - NDP responder response event handler |
| * @handle: wma handle |
| * @event_info: event handler data |
| * @len: length of event_info |
| * |
| * Handler for WMI_NDP_RESPONDER_RSP_EVENTID |
| * Return: 0 on success, negative errno on failure |
| */ |
| static int wma_ndp_responder_rsp_event_handler(void *handle, |
| uint8_t *event_info, uint32_t len) |
| { |
| WMI_NDP_RESPONDER_RSP_EVENTID_param_tlvs *event; |
| wmi_ndp_responder_rsp_event_fixed_param *fixed_params; |
| struct ndp_responder_rsp_event rsp; |
| |
| event = (WMI_NDP_RESPONDER_RSP_EVENTID_param_tlvs *)event_info; |
| fixed_params = event->fixed_param; |
| |
| rsp.vdev_id = fixed_params->vdev_id; |
| rsp.transaction_id = fixed_params->transaction_id; |
| rsp.reason = fixed_params->reason_code; |
| rsp.status = fixed_params->rsp_status; |
| rsp.create_peer = fixed_params->create_peer; |
| WMI_MAC_ADDR_TO_CHAR_ARRAY(&fixed_params->peer_ndi_mac_addr, |
| rsp.peer_mac_addr.bytes); |
| |
| WMA_LOGE(FL("WMI_NDP_RESPONDER_RSP_EVENTID(0x%X) received. vdev_id: %d, peer_mac_addr: %pM, transaction_id: %d, status_code %d, reason_code: %d, create_peer: %d"), |
| WMI_NDP_RESPONDER_RSP_EVENTID, rsp.vdev_id, |
| rsp.peer_mac_addr.bytes, rsp.transaction_id, |
| rsp.status, rsp.reason, rsp.create_peer); |
| |
| return wma_send_ndp_responder_rsp(&rsp); |
| } |
| |
| /** |
| * wma_ndp_confirm_event_handler() - NDP confirm event handler |
| * @handle: wma handle |
| * @event_info: event handler data |
| * @len: length of event_info |
| * |
| * Handler for WMI_NDP_CONFIRM_EVENTID |
| * Return: 0 on success, negative errno on failure |
| */ |
| static int wma_ndp_confirm_event_handler(void *handle, uint8_t *event_info, |
| uint32_t len) |
| { |
| struct ndp_confirm_event *ndp_confirm; |
| vos_msg_t msg = {0}; |
| WMI_NDP_CONFIRM_EVENTID_param_tlvs *event; |
| wmi_ndp_confirm_event_fixed_param *fixed_params; |
| VOS_STATUS status; |
| |
| event = (WMI_NDP_CONFIRM_EVENTID_param_tlvs *) event_info; |
| fixed_params = (wmi_ndp_confirm_event_fixed_param *)event->fixed_param; |
| WMA_LOGE(FL("WMI_NDP_CONFIRM_EVENTID(0x%X) recieved. vdev %d, ndp_instance %d, rsp_code %d, reason_code: %d, num_active_ndps_on_peer: %d"), |
| WMI_NDP_CONFIRM_EVENTID, fixed_params->vdev_id, |
| fixed_params->ndp_instance_id, fixed_params->rsp_code, |
| fixed_params->reason_code, |
| fixed_params->num_active_ndps_on_peer); |
| |
| WMA_LOGE(FL("ndp_cfg - %d bytes"), fixed_params->ndp_cfg_len); |
| VOS_TRACE_HEX_DUMP(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_DEBUG, |
| &event->ndp_cfg, fixed_params->ndp_cfg_len); |
| |
| WMA_LOGE(FL("ndp_app_info - %d bytes"), fixed_params->ndp_app_info_len); |
| VOS_TRACE_HEX_DUMP(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_DEBUG, |
| &event->ndp_app_info, fixed_params->ndp_app_info_len); |
| |
| ndp_confirm = vos_mem_malloc(sizeof(*ndp_confirm)); |
| if (!ndp_confirm) { |
| WMA_LOGP(FL("Failed to allocate memory")); |
| return VOS_STATUS_E_NOMEM; |
| } |
| vos_mem_zero(ndp_confirm, sizeof(*ndp_confirm)); |
| |
| ndp_confirm->vdev_id = fixed_params->vdev_id; |
| ndp_confirm->ndp_instance_id = fixed_params->ndp_instance_id; |
| ndp_confirm->rsp_code = fixed_params->rsp_code; |
| ndp_confirm->reason_code = fixed_params->reason_code; |
| ndp_confirm->num_active_ndps_on_peer = |
| fixed_params->num_active_ndps_on_peer; |
| |
| WMI_MAC_ADDR_TO_CHAR_ARRAY(&fixed_params->peer_ndi_mac_addr, |
| ndp_confirm->peer_ndi_mac_addr.bytes); |
| |
| ndp_confirm->ndp_info.ndp_app_info_len = fixed_params->ndp_app_info_len; |
| if (ndp_confirm->ndp_info.ndp_app_info_len) { |
| ndp_confirm->ndp_info.ndp_app_info = |
| vos_mem_malloc(fixed_params->ndp_app_info_len); |
| if (NULL == ndp_confirm->ndp_info.ndp_app_info) { |
| WMA_LOGE(FL("malloc failed")); |
| vos_mem_free(ndp_confirm); |
| return VOS_STATUS_E_NOMEM; |
| } |
| vos_mem_copy(&ndp_confirm->ndp_info.ndp_app_info, |
| event->ndp_app_info, |
| ndp_confirm->ndp_info.ndp_app_info_len); |
| } |
| msg.type = SIR_HAL_NDP_CONFIRM; |
| msg.bodyptr = ndp_confirm; |
| msg.bodyval = 0; |
| WMA_LOGE(FL("Sending SIR_HAL_NDP_CONFIRM msg to PE")); |
| status = vos_mq_post_message(VOS_MODULE_ID_PE, &msg); |
| if (!VOS_IS_STATUS_SUCCESS(status)) { |
| WMA_LOGE(FL("fail to post SIR_HAL_NDP_CONFIRM msg to PE")); |
| vos_mem_free(ndp_confirm->ndp_info.ndp_app_info); |
| vos_mem_free(ndp_confirm); |
| } |
| |
| return VOS_STATUS_SUCCESS; |
| } |
| |
| /** |
| * wma_ndp_end_response_event_handler() - NDP end response event handler |
| * @handle: wma handle |
| * @event_info: event handler data |
| * @len: length of event_info |
| * |
| * Handler for WMI_NDP_END_RSP_EVENTID |
| * Return: 0 on success, negative errno on failure |
| */ |
| static int wma_ndp_end_response_event_handler(void *handle, |
| uint8_t *event_info, uint32_t len) |
| { |
| int ret = 0; |
| VOS_STATUS status; |
| vos_msg_t pe_msg = {0}; |
| struct ndp_end_rsp_event *end_rsp; |
| WMI_NDP_END_RSP_EVENTID_param_tlvs *event; |
| wmi_ndp_end_rsp_event_fixed_param *fixed_params = NULL; |
| |
| event = (WMI_NDP_END_RSP_EVENTID_param_tlvs *) event_info; |
| fixed_params = (wmi_ndp_end_rsp_event_fixed_param *)event->fixed_param; |
| WMA_LOGD(FL("WMI_NDP_END_RSP_EVENTID(0x%X) recieved. transaction_id: %d, rsp_status: %d, reason_code: %d"), |
| WMI_NDP_END_RSP_EVENTID, fixed_params->transaction_id, |
| fixed_params->rsp_status, fixed_params->reason_code); |
| |
| end_rsp = vos_mem_malloc(sizeof(*end_rsp)); |
| if (NULL == end_rsp) { |
| WMA_LOGE("malloc failed"); |
| pe_msg.bodyval = true; |
| ret = -ENOMEM; |
| goto send_ndp_end_rsp; |
| } |
| pe_msg.bodyptr = end_rsp; |
| vos_mem_zero(end_rsp, sizeof(*end_rsp)); |
| |
| end_rsp->transaction_id = fixed_params->transaction_id; |
| end_rsp->reason = fixed_params->reason_code; |
| end_rsp->status = fixed_params->rsp_status; |
| |
| send_ndp_end_rsp: |
| pe_msg.type = SIR_HAL_NDP_END_RSP; |
| WMA_LOGD(FL("Sending SIR_HAL_NDP_END_RSP msg to PE")); |
| status = vos_mq_post_message(VOS_MODULE_ID_PE, &pe_msg); |
| if (!VOS_IS_STATUS_SUCCESS(status)) { |
| WMA_LOGE("SIR_HAL_NDP_END_RSP to PE failed"); |
| vos_mem_free(end_rsp); |
| ret = -EINVAL; |
| } |
| |
| return ret; |
| } |
| |
| /** |
| * wma_ndp_end_indication_event_handler() - NDP end indication event handler |
| * @handle: wma handle |
| * @event_info: event handler data |
| * @len: length of event_info |
| * |
| * Handler for WMI_NDP_END_INDICATION_EVENTID |
| * Return: 0 on success, negative errno on failure |
| */ |
| static int wma_ndp_end_indication_event_handler(void *handle, |
| uint8_t *event_info, uint32_t len) |
| { |
| WMI_NDP_END_INDICATION_EVENTID_param_tlvs *event; |
| wmi_ndp_end_indication *ind; |
| vos_msg_t pe_msg; |
| struct ndp_end_indication_event *ndp_event_buf; |
| VOS_STATUS vos_status; |
| int i; |
| v_MACADDR_t peer_addr; |
| int buf_size; |
| |
| event = (WMI_NDP_END_INDICATION_EVENTID_param_tlvs *) event_info; |
| |
| if (event->num_ndp_end_indication_list == 0) { |
| WMA_LOGE( |
| FL("Error: Event ignored, 0 ndp instances")); |
| return -EINVAL; |
| } |
| |
| WMA_LOGD(FL("number of ndp instances = %d"), |
| event->num_ndp_end_indication_list); |
| if (event->num_ndp_end_indication_list > ((WMA_SVC_MSG_MAX_SIZE - |
| sizeof(*ndp_event_buf)) / sizeof(ndp_event_buf->ndp_map[0]))) { |
| WMA_LOGE("%s: excess data received from fw num_ndp_end_indication_list %d", |
| __func__, event->num_ndp_end_indication_list); |
| return -EINVAL; |
| } |
| buf_size = sizeof(*ndp_event_buf) + event->num_ndp_end_indication_list * |
| sizeof(ndp_event_buf->ndp_map[0]); |
| ndp_event_buf = vos_mem_malloc(buf_size); |
| if (!ndp_event_buf) { |
| WMA_LOGP(FL("Failed to allocate memory")); |
| return -ENOMEM; |
| } |
| vos_mem_zero(ndp_event_buf, buf_size); |
| ndp_event_buf->num_ndp_ids = event->num_ndp_end_indication_list; |
| |
| ind = event->ndp_end_indication_list; |
| for (i = 0; i < ndp_event_buf->num_ndp_ids; i++) { |
| WMI_MAC_ADDR_TO_CHAR_ARRAY( |
| &ind[i].peer_ndi_mac_addr, |
| peer_addr.bytes); |
| WMA_LOGD( |
| FL("ind[%d]: type %d, reason_code %d, instance_id %d num_active %d MAC: " MAC_ADDRESS_STR), |
| i, |
| ind[i].type, |
| ind[i].reason_code, |
| ind[i].ndp_instance_id, |
| ind[i].num_active_ndps_on_peer, |
| MAC_ADDR_ARRAY(peer_addr.bytes)); |
| |
| /* Add each instance entry to the list */ |
| ndp_event_buf->ndp_map[i].ndp_instance_id = |
| ind[i].ndp_instance_id; |
| ndp_event_buf->ndp_map[i].vdev_id = ind[i].vdev_id; |
| WMI_MAC_ADDR_TO_CHAR_ARRAY(&ind[i].peer_ndi_mac_addr, |
| ndp_event_buf->ndp_map[i].peer_ndi_mac_addr.bytes); |
| ndp_event_buf->ndp_map[i].num_active_ndp_sessions = |
| ind[i].num_active_ndps_on_peer; |
| ndp_event_buf->ndp_map[i].type = ind[i].type; |
| ndp_event_buf->ndp_map[i].reason_code = |
| ind[i].reason_code; |
| } |
| |
| pe_msg.type = SIR_HAL_NDP_END_IND; |
| pe_msg.bodyptr = ndp_event_buf; |
| pe_msg.bodyval = 0; |
| vos_status = vos_mq_post_message(VOS_MODULE_ID_PE, &pe_msg); |
| if (VOS_IS_STATUS_SUCCESS(vos_status)) { |
| return 0; |
| } |
| |
| WMA_LOGE(FL("failed to post msg to PE")); |
| vos_mem_free(ndp_event_buf); |
| return -EINVAL; |
| } |
| |
| /** |
| * wma_ndp_initiator_rsp_event_handler() -NDP initiator rsp event handler |
| * @handle: wma handle |
| * @event_info: event handler data |
| * @len: length of event_info |
| * |
| * Handler for WMI_NDP_INITIATOR_RSP_EVENTID |
| * Return: 0 on success, negative errno on failure |
| */ |
| static int wma_ndp_initiator_rsp_event_handler(void *handle, |
| uint8_t *event_info, uint32_t len) |
| { |
| VOS_STATUS status; |
| vos_msg_t pe_msg = {0}; |
| WMI_NDP_INITIATOR_RSP_EVENTID_param_tlvs *event; |
| wmi_ndp_initiator_rsp_event_fixed_param *fixed_params; |
| struct ndp_initiator_rsp *rsp; |
| |
| rsp = vos_mem_malloc(sizeof(*rsp)); |
| if (NULL == rsp) { |
| WMA_LOGE(FL("Invalid rsp_ind")); |
| return VOS_STATUS_E_INVAL; |
| } |
| |
| event = (WMI_NDP_INITIATOR_RSP_EVENTID_param_tlvs *)event_info; |
| fixed_params = event->fixed_param; |
| |
| rsp->vdev_id = fixed_params->vdev_id; |
| rsp->transaction_id = fixed_params->transaction_id; |
| rsp->ndp_instance_id = fixed_params->ndp_instance_id; |
| rsp->status = fixed_params->rsp_status; |
| rsp->reason = fixed_params->reason_code; |
| |
| pe_msg.type = SIR_HAL_NDP_INITIATOR_RSP; |
| pe_msg.bodyptr = rsp; |
| status = vos_mq_post_message(VOS_MODULE_ID_PE, &pe_msg); |
| if (!VOS_IS_STATUS_SUCCESS(status)) { |
| WMA_LOGE("SIR_HAL_NDP_INITIATOR_RSP to PE failed"); |
| vos_mem_free(rsp); |
| return status; |
| } |
| |
| return status; |
| } |
| |
| /** |
| * wma_ndp_register_all_event_handlers() - Register all NDP event handlers |
| * @wma_handle: WMA context |
| * |
| * Register the event handlers for NAN data path events from firmware. |
| * |
| * Return: None |
| */ |
| void wma_ndp_register_all_event_handlers(tp_wma_handle wma_handle) |
| { |
| WMA_LOGD(FL("Register WMI_NDP_INITIATOR_RSP_EVENTID")); |
| wmi_unified_register_event_handler(wma_handle->wmi_handle, |
| WMI_NDP_INITIATOR_RSP_EVENTID, |
| wma_ndp_initiator_rsp_event_handler); |
| |
| WMA_LOGD(FL("Register WMI_NDP_RESPONDER_RSP_EVENTID")); |
| wmi_unified_register_event_handler(wma_handle->wmi_handle, |
| WMI_NDP_RESPONDER_RSP_EVENTID, |
| wma_ndp_responder_rsp_event_handler); |
| |
| WMA_LOGD(FL("Register WMI_NDP_END_RSP_EVENTID")); |
| wmi_unified_register_event_handler(wma_handle->wmi_handle, |
| WMI_NDP_END_RSP_EVENTID, |
| wma_ndp_end_response_event_handler); |
| |
| WMA_LOGD(FL("Register WMI_NDP_INDICATION_EVENTID")); |
| wmi_unified_register_event_handler(wma_handle->wmi_handle, |
| WMI_NDP_INDICATION_EVENTID, |
| wma_ndp_indication_event_handler); |
| |
| WMA_LOGD(FL("Register WMI_NDP_CONFIRM_EVENTID")); |
| wmi_unified_register_event_handler(wma_handle->wmi_handle, |
| WMI_NDP_CONFIRM_EVENTID, |
| wma_ndp_confirm_event_handler); |
| |
| WMA_LOGD(FL("Register WMI_NDP_END_INDICATION_EVENTID")); |
| wmi_unified_register_event_handler(wma_handle->wmi_handle, |
| WMI_NDP_END_INDICATION_EVENTID, |
| wma_ndp_end_indication_event_handler); |
| } |
| |
| /** |
| * wma_ndp_unregister_all_event_handlers() - Unregister all NDP event handlers |
| * @wma_handle: WMA context |
| * |
| * Register the event handlers for NAN data path events from firmware. |
| * |
| * Return: None |
| */ |
| void wma_ndp_unregister_all_event_handlers(tp_wma_handle wma_handle) |
| { |
| WMA_LOGD(FL("Unregister WMI_NDP_INITIATOR_RSP_EVENTID")); |
| wmi_unified_unregister_event_handler(wma_handle->wmi_handle, |
| WMI_NDP_INITIATOR_RSP_EVENTID); |
| |
| WMA_LOGD(FL("Unregister WMI_NDP_RESPONDER_RSP_EVENTID")); |
| wmi_unified_unregister_event_handler(wma_handle->wmi_handle, |
| WMI_NDP_RESPONDER_RSP_EVENTID); |
| |
| WMA_LOGD(FL("Unregister WMI_NDP_END_RSP_EVENTID")); |
| wmi_unified_unregister_event_handler(wma_handle->wmi_handle, |
| WMI_NDP_END_RSP_EVENTID); |
| |
| WMA_LOGD(FL("Unregister WMI_NDP_INDICATION_EVENTID")); |
| wmi_unified_unregister_event_handler(wma_handle->wmi_handle, |
| WMI_NDP_INDICATION_EVENTID); |
| |
| WMA_LOGD(FL("Unregister WMI_NDP_CONFIRM_EVENTID")); |
| wmi_unified_unregister_event_handler(wma_handle->wmi_handle, |
| WMI_NDP_CONFIRM_EVENTID); |
| |
| WMA_LOGD(FL("Unregister WMI_NDP_END_INDICATION_EVENTID")); |
| wmi_unified_unregister_event_handler(wma_handle->wmi_handle, |
| WMI_NDP_END_INDICATION_EVENTID); |
| } |
| |
| /** |
| * wma_ndp_add_wow_wakeup_event() - Add Wake on Wireless event for NDP |
| * @wma_handle: WMA context |
| * @enable: dis/enable flag to enable the bit for WOW_NAN_DATA_EVENT |
| * |
| * Enables the firmware to wake up the host on NAN data path event. |
| * All NDP events such as NDP_INDICATION, NDP_CONFIRM, etc. use the |
| * same event. They can be distinguished using their TLV tags. |
| * |
| * Return: none |
| */ |
| void wma_ndp_add_wow_wakeup_event(tp_wma_handle wma_handle, |
| bool enable) |
| { |
| wma_add_wow_wakeup_event(wma_handle, WOW_NAN_DATA_EVENT, enable); |
| } |
| |
| /** |
| * wma_ndp_get_eventid_from_tlvtag() - map tlv tag to event id |
| * @tag: WMI TLV tag |
| * |
| * map the tag to known NDP event fixed_param tags and return the |
| * corresponding NDP event id. |
| * |
| * Return: 0 if TLV tag is invalid |
| * else return corresponding WMI event id |
| */ |
| static int wma_ndp_get_eventid_from_tlvtag(uint32_t tag) |
| { |
| uint32_t event_id; |
| |
| switch (tag) { |
| case WMITLV_TAG_STRUC_wmi_ndp_initiator_rsp_event_fixed_param: |
| event_id = WMI_NDP_INITIATOR_RSP_EVENTID; |
| break; |
| |
| case WMITLV_TAG_STRUC_wmi_ndp_responder_rsp_event_fixed_param: |
| event_id = WMI_NDP_RESPONDER_RSP_EVENTID; |
| break; |
| |
| case WMITLV_TAG_STRUC_wmi_ndp_end_rsp_event_fixed_param: |
| event_id = WMI_NDP_END_RSP_EVENTID; |
| break; |
| |
| case WMITLV_TAG_STRUC_wmi_ndp_indication_event_fixed_param: |
| event_id = WMI_NDP_INDICATION_EVENTID; |
| break; |
| |
| case WMITLV_TAG_STRUC_wmi_ndp_confirm_event_fixed_param: |
| event_id = WMI_NDP_CONFIRM_EVENTID; |
| break; |
| |
| case WMITLV_TAG_STRUC_wmi_ndp_end_indication_event_fixed_param: |
| event_id = WMI_NDP_END_INDICATION_EVENTID; |
| break; |
| |
| default: |
| event_id = 0; |
| WMA_LOGE(FL("Unknown tag: %d"), tag); |
| break; |
| } |
| |
| WMA_LOGI(FL("For tag %d WMI event 0x%x"), tag, event_id); |
| return event_id; |
| } |
| |
| /** |
| * wma_ndp_wow_event_callback() - NAN data path wow event callback |
| * @handle: WMA handle |
| * @event: event buffer |
| * @len: length of @event buffer |
| * |
| * The wow event WOW_REASON_NAN_DATA is followed by the payload of the event |
| * which generated the wow event. |
| * Payload is 4 bytes of length followed by event buffer. First 4 bytes |
| * of event buffer is common tlv header, which is a combination |
| * of tag (higher 2 bytes) and length (lower 2 bytes). The tag is used to |
| * identify the event which triggered wow event. |
| * |
| * Return: none |
| */ |
| void wma_ndp_wow_event_callback(void *handle, void *event, |
| uint32_t len) |
| { |
| uint32_t id; |
| int tlv_ok_status = 0; |
| void *wmi_cmd_struct_ptr = NULL; |
| uint32_t tag = WMITLV_GET_TLVTAG(WMITLV_GET_HDR(event)); |
| |
| /* Reverse map fixed params tag to EVENT_ID */ |
| id = wma_ndp_get_eventid_from_tlvtag(tag); |
| if (!id) { |
| WMA_LOGE(FL("Invalid Tag: %d"), tag); |
| return; |
| } |
| |
| tlv_ok_status = wmitlv_check_and_pad_event_tlvs(handle, event, len, |
| id, |
| &wmi_cmd_struct_ptr); |
| if (tlv_ok_status != 0) { |
| WMA_LOGE(FL("Invalid Tag: %d could not check and pad tlvs"), |
| tag); |
| return; |
| } |
| |
| switch (id) { |
| case WMI_NDP_INITIATOR_RSP_EVENTID: |
| wma_ndp_initiator_rsp_event_handler(handle, |
| wmi_cmd_struct_ptr, len); |
| break; |
| |
| case WMI_NDP_RESPONDER_RSP_EVENTID: |
| wma_ndp_responder_rsp_event_handler(handle, |
| wmi_cmd_struct_ptr, len); |
| break; |
| |
| case WMI_NDP_END_RSP_EVENTID: |
| wma_ndp_end_response_event_handler(handle, |
| wmi_cmd_struct_ptr, len); |
| break; |
| |
| case WMI_NDP_INDICATION_EVENTID: |
| wma_ndp_indication_event_handler(handle, |
| wmi_cmd_struct_ptr, len); |
| break; |
| |
| case WMI_NDP_CONFIRM_EVENTID: |
| wma_ndp_confirm_event_handler(handle, |
| wmi_cmd_struct_ptr, len); |
| break; |
| |
| case WMI_NDP_END_INDICATION_EVENTID: |
| wma_ndp_end_indication_event_handler(handle, |
| wmi_cmd_struct_ptr, len); |
| break; |
| |
| default: |
| WMA_LOGE(FL("Unknown tag: %d"), tag); |
| break; |
| } |
| wmitlv_free_allocated_event_tlvs(id, &wmi_cmd_struct_ptr); |
| } |
| |
| /** |
| * wma_add_bss_ndi_mode() - Process BSS creation request while adding NaN |
| * Data interface |
| * @wma: wma handle |
| * @add_bss: Parameters for ADD_BSS command |
| * |
| * Sends VDEV_START command to firmware |
| * Return: None |
| */ |
| void wma_add_bss_ndi_mode(tp_wma_handle wma, tpAddBssParams add_bss) |
| { |
| ol_txrx_pdev_handle pdev; |
| struct wma_vdev_start_req req; |
| ol_txrx_peer_handle peer = NULL; |
| struct wma_target_req *msg; |
| uint8_t vdev_id, peer_id; |
| VOS_STATUS status; |
| uint8_t nss_2g, nss_5g; |
| |
| WMA_LOGE("%s: enter", __func__); |
| if (NULL == wma_find_vdev_by_addr(wma, add_bss->bssId, &vdev_id)) { |
| WMA_LOGE("%s: Failed to find vdev", __func__); |
| goto send_fail_resp; |
| } |
| pdev = vos_get_context(VOS_MODULE_ID_TXRX, wma->vos_context); |
| |
| if (NULL == pdev) { |
| WMA_LOGE("%s: Failed to get pdev", __func__); |
| goto send_fail_resp; |
| } |
| |
| nss_2g = wma->interfaces[vdev_id].nss_2g; |
| nss_5g = wma->interfaces[vdev_id].nss_5g; |
| wma_set_bss_rate_flags(&wma->interfaces[vdev_id], add_bss); |
| |
| peer = ol_txrx_find_peer_by_addr(pdev, add_bss->selfMacAddr, &peer_id); |
| if (!peer) { |
| WMA_LOGE("%s Failed to find peer %pM", __func__, |
| add_bss->selfMacAddr); |
| goto send_fail_resp; |
| } |
| |
| msg = wma_fill_vdev_req(wma, vdev_id, WDA_ADD_BSS_REQ, |
| WMA_TARGET_REQ_TYPE_VDEV_START, add_bss, |
| WMA_VDEV_START_REQUEST_TIMEOUT); |
| if (!msg) { |
| WMA_LOGE("%s Failed to allocate vdev request vdev_id %d", |
| __func__, vdev_id); |
| goto send_fail_resp; |
| } |
| |
| add_bss->staContext.staIdx = ol_txrx_local_peer_id(peer); |
| |
| /* |
| * beacon_intval, dtim_period, hidden_ssid, is_dfs, ssid |
| * will be ignored for NDI device. |
| */ |
| vos_mem_zero(&req, sizeof(req)); |
| req.vdev_id = vdev_id; |
| req.chan = add_bss->currentOperChannel; |
| req.chan_offset = add_bss->currentExtChannel; |
| req.vht_capable = add_bss->vhtCapable; |
| req.max_txpow = add_bss->maxTxPower; |
| req.oper_mode = add_bss->operMode; |
| |
| status = wma_vdev_start(wma, &req, VOS_FALSE); |
| if (status != VOS_STATUS_SUCCESS) { |
| wma_remove_vdev_req(wma, vdev_id, |
| WMA_TARGET_REQ_TYPE_VDEV_START); |
| goto send_fail_resp; |
| } |
| WMA_LOGI("%s: vdev start request for NDI sent to target", __func__); |
| |
| /* Initialize protection mode to no protection */ |
| if (wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id, |
| WMI_VDEV_PARAM_PROTECTION_MODE, |
| IEEE80211_PROT_NONE)) { |
| WMA_LOGE("Failed to initialize protection mode"); |
| } |
| |
| return; |
| send_fail_resp: |
| add_bss->status = VOS_STATUS_E_FAILURE; |
| wma_send_msg(wma, WDA_ADD_BSS_RSP, (void *)add_bss, 0); |
| } |
| |
| /** |
| * wma_delete_all_nan_remote_peers() - Delete all nan peer |
| * @wma: wma handle |
| * @vdev_id: vdev id |
| * |
| * Return: void |
| */ |
| void wma_delete_all_nan_remote_peers(tp_wma_handle wma, uint32_t vdev_id) |
| { |
| ol_txrx_vdev_handle vdev; |
| ol_txrx_peer_handle peer, temp; |
| |
| if (!wma || vdev_id >= wma->max_bssid) |
| return; |
| |
| vdev = wma->interfaces[vdev_id].handle; |
| if (!vdev) |
| return; |
| |
| /* remove all remote peers of ndi*/ |
| adf_os_spin_lock_bh(&vdev->pdev->peer_ref_mutex); |
| |
| temp = NULL; |
| TAILQ_FOREACH_REVERSE(peer, &vdev->peer_list, |
| peer_list_t, peer_list_elem) { |
| if (temp) { |
| adf_os_spin_unlock_bh(&vdev->pdev->peer_ref_mutex); |
| if (adf_os_atomic_read( |
| &temp->delete_in_progress) == 0) |
| wma_remove_peer(wma, temp->mac_addr.raw, |
| vdev_id, temp, VOS_FALSE); |
| adf_os_spin_lock_bh(&vdev->pdev->peer_ref_mutex); |
| } |
| /* self peer is deleted last */ |
| if (peer == TAILQ_FIRST(&vdev->peer_list)) { |
| WMA_LOGE("%s: self peer removed", __func__); |
| break; |
| } else |
| temp = peer; |
| } |
| adf_os_spin_unlock_bh(&vdev->pdev->peer_ref_mutex); |
| |
| /* remove ndi self peer last */ |
| peer = TAILQ_FIRST(&vdev->peer_list); |
| wma_remove_peer(wma, peer->mac_addr.raw, vdev_id, peer, |
| false); |
| } |
| /** |
| * wma_add_sta_ndi_mode() - Process ADD_STA for NaN Data path |
| * @wma: wma handle |
| * @add_sta: Parameters of ADD_STA command |
| * |
| * Sends CREATE_PEER command to firmware |
| * Return: void |
| */ |
| void wma_add_sta_ndi_mode(tp_wma_handle wma, tpAddStaParams add_sta) |
| { |
| enum ol_txrx_peer_state state = ol_txrx_peer_state_conn; |
| ol_txrx_pdev_handle pdev; |
| ol_txrx_vdev_handle vdev; |
| ol_txrx_peer_handle peer; |
| u_int8_t peer_id; |
| VOS_STATUS status; |
| struct wma_txrx_node *iface; |
| |
| pdev = vos_get_context(VOS_MODULE_ID_TXRX, wma->vos_context); |
| |
| if (NULL == pdev) { |
| WMA_LOGE(FL("Failed to find pdev")); |
| add_sta->status = VOS_STATUS_E_FAILURE; |
| goto send_rsp; |
| } |
| |
| vdev = wma_find_vdev_by_id(wma, add_sta->smesessionId); |
| if (!vdev) { |
| WMA_LOGE(FL("Failed to find vdev")); |
| add_sta->status = VOS_STATUS_E_FAILURE; |
| goto send_rsp; |
| } |
| |
| iface = &wma->interfaces[vdev->vdev_id]; |
| WMA_LOGD(FL("vdev: %d, peer_mac_addr: "MAC_ADDRESS_STR), |
| add_sta->smesessionId, MAC_ADDR_ARRAY(add_sta->staMac)); |
| |
| peer = ol_txrx_find_peer_by_addr_and_vdev(pdev, vdev, add_sta->staMac, |
| &peer_id); |
| if (peer) { |
| WMA_LOGE(FL("NDI peer already exists, peer_addr %pM"), |
| add_sta->staMac); |
| add_sta->status = VOS_STATUS_E_EXISTS; |
| goto send_rsp; |
| } |
| |
| /* |
| * The code above only checks the peer existence on its own vdev. |
| * Need to check whether the peer exists on other vDevs because firmware |
| * can't create the peer if the peer with same MAC address already |
| * exists on the pDev. As this peer belongs to other vDevs, just return |
| * here. |
| */ |
| peer = ol_txrx_find_peer_by_addr(pdev, add_sta->staMac, &peer_id); |
| if (peer) { |
| WMA_LOGE(FL("vdev:%d, peer exists on other vdev with peer_addr %pM and peer_id %d"), |
| vdev->vdev_id, add_sta->staMac, peer_id); |
| add_sta->status = VOS_STATUS_E_EXISTS; |
| goto send_rsp; |
| } |
| |
| status = wma_create_peer(wma, pdev, vdev, add_sta->staMac, |
| WMI_PEER_TYPE_NAN_DATA, add_sta->smesessionId, |
| VOS_FALSE); |
| if (status != VOS_STATUS_SUCCESS) { |
| WMA_LOGE(FL("Failed to create peer for %pM"), add_sta->staMac); |
| add_sta->status = status; |
| goto send_rsp; |
| } |
| |
| peer = ol_txrx_find_peer_by_addr_and_vdev(pdev, vdev, add_sta->staMac, |
| &peer_id); |
| if (!peer) { |
| WMA_LOGE(FL("Failed to find peer handle using peer mac %pM"), |
| add_sta->staMac); |
| add_sta->status = VOS_STATUS_E_FAILURE; |
| wma_remove_peer(wma, add_sta->staMac, add_sta->smesessionId, |
| peer, VOS_FALSE); |
| goto send_rsp; |
| } |
| |
| WMA_LOGD(FL("Moving peer %pM to state %d"), add_sta->staMac, state); |
| ol_txrx_peer_state_update(pdev, add_sta->staMac, state); |
| |
| add_sta->staIdx = ol_txrx_local_peer_id(peer); |
| add_sta->nss = iface->nss; |
| add_sta->status = VOS_STATUS_SUCCESS; |
| send_rsp: |
| WMA_LOGD(FL("Sending add sta rsp to umac (mac:%pM, status:%d)"), |
| add_sta->staMac, add_sta->status); |
| wma_send_msg(wma, WDA_ADD_STA_RSP, (void *)add_sta, 0); |
| } |
| |
| /** |
| * wma_delete_sta_req_ndi_mode() - Process DEL_STA request for NDI data peer |
| * @wma: WMA context |
| * @del_sta: DEL_STA parameters from LIM |
| * |
| * Removes wma/txrx peer entry for the NDI STA |
| * |
| * Return: None |
| */ |
| void wma_delete_sta_req_ndi_mode(tp_wma_handle wma, |
| tpDeleteStaParams del_sta) |
| { |
| ol_txrx_pdev_handle pdev; |
| struct ol_txrx_peer_t *peer; |
| |
| pdev = vos_get_context(VOS_MODULE_ID_TXRX, wma->vos_context); |
| |
| if (!pdev) { |
| WMA_LOGE(FL("Failed to get pdev")); |
| del_sta->status = VOS_STATUS_E_FAILURE; |
| goto send_del_rsp; |
| } |
| |
| peer = ol_txrx_peer_find_by_local_id(pdev, del_sta->staIdx); |
| if (!peer) { |
| WMA_LOGE(FL("Failed to get peer handle using peer id %d"), |
| del_sta->staIdx); |
| del_sta->status = VOS_STATUS_E_FAILURE; |
| goto send_del_rsp; |
| } |
| |
| wma_remove_peer(wma, peer->mac_addr.raw, del_sta->smesessionId, peer, |
| false); |
| del_sta->status = VOS_STATUS_SUCCESS; |
| |
| send_del_rsp: |
| if (del_sta->respReqd) { |
| WMA_LOGD(FL("Sending del rsp to umac (status: %d)"), |
| del_sta->status); |
| wma_send_msg(wma, WDA_DELETE_STA_RSP, del_sta, 0); |
| } |
| } |
| |
| |