diff --git a/wmi/inc/wmi_unified_api.h b/wmi/inc/wmi_unified_api.h index 74d9b60ca8..ec34cabf29 100644 --- a/wmi/inc/wmi_unified_api.h +++ b/wmi/inc/wmi_unified_api.h @@ -3649,4 +3649,31 @@ wmi_extract_oem_response_param(wmi_unified_t wmi_hdl, void *resp_buf, */ uint32_t wmi_critical_events_in_flight(struct wmi_unified *wmi); + +#ifdef FEATURE_ANI_LEVEL_REQUEST +/** + * wmi_unified_ani_level_cmd_send() - WMI function to send get ani level cmd + * @wmi_hdl: WMI handle + * @freqs: pointer to list of freqs for which ANI levels are to be fetched + * @num_freqs: number of freqs in the above parameter + * + * Return: QDF_STATUS_SUCCESS if success, else returns proper error code. + */ +QDF_STATUS wmi_unified_ani_level_cmd_send(wmi_unified_t wmi_handle, + uint32_t *freqs, + uint8_t num_freqs); + +/** + * wmi_unified_extract_ani_level() - WMI function to receive ani level cmd + * @wmi_hdl: WMI handle + * @info: pointer to ANI data received from the FW and stored in HOST + * @num_freqs: number of freqs in the above parameter + * + * Return: QDF_STATUS_SUCCESS if success, else returns proper error code. + */ +QDF_STATUS wmi_unified_extract_ani_level(wmi_unified_t wmi_handle, + uint8_t *data, + struct wmi_host_ani_level_event **info, + uint32_t *num_freqs); +#endif /* FEATURE_ANI_LEVEL_REQUEST */ #endif /* _WMI_UNIFIED_API_H_ */ diff --git a/wmi/inc/wmi_unified_param.h b/wmi/inc/wmi_unified_param.h index 3d95beddf7..6e4edffa86 100644 --- a/wmi/inc/wmi_unified_param.h +++ b/wmi/inc/wmi_unified_param.h @@ -4543,6 +4543,7 @@ typedef enum { wmi_get_elna_bypass_event_id, wmi_motion_det_host_eventid, wmi_motion_det_base_line_host_eventid, + wmi_get_ani_level_event_id, wmi_events_max, } wmi_conv_event_id; @@ -7846,4 +7847,17 @@ struct wmi_rx_pkt_protocol_routing_info { uint32_t meta_data; }; #endif /* WLAN_SUPPORT_RX_PROTOCOL_TYPE_TAG */ + +#ifdef FEATURE_ANI_LEVEL_REQUEST +/* Maximum number of freqs for which ANI level can be requested */ +#define MAX_NUM_FREQS_FOR_ANI_LEVEL 20 + +/* A valid ANI level lies between 0 to 9 */ +#define MAX_ANI_LEVEL 9 + +struct wmi_host_ani_level_event { + uint32_t chan_freq; + uint32_t ani_level; +}; +#endif /* FEATURE_ANI_LEVEL_REQUEST */ #endif /* _WMI_UNIFIED_PARAM_H_ */ diff --git a/wmi/inc/wmi_unified_priv.h b/wmi/inc/wmi_unified_priv.h index de921011a6..2ed0dcc777 100644 --- a/wmi/inc/wmi_unified_priv.h +++ b/wmi/inc/wmi_unified_priv.h @@ -2046,6 +2046,15 @@ QDF_STATUS (*extract_get_elna_bypass_resp)(wmi_unified_t wmi_handle, void *resp_buf, struct get_elna_bypass_response *resp); #endif /* WLAN_FEATURE_ELNA */ + +#ifdef FEATURE_ANI_LEVEL_REQUEST +QDF_STATUS (*send_ani_level_cmd)(wmi_unified_t wmi_handle, uint32_t *freqs, + uint8_t num_freqs); + +QDF_STATUS (*extract_ani_level)(uint8_t *evt_buf, + struct wmi_host_ani_level_event **info, + uint32_t *num_freqs); +#endif /* FEATURE_ANI_LEVEL_REQUEST */ }; /* Forward declartion for psoc*/ diff --git a/wmi/src/wmi_unified_api.c b/wmi/src/wmi_unified_api.c index c833172bf6..cc0e3488a6 100644 --- a/wmi/src/wmi_unified_api.c +++ b/wmi/src/wmi_unified_api.c @@ -2977,3 +2977,28 @@ QDF_STATUS wmi_unified_extract_hw_mode_resp(wmi_unified_t wmi, return QDF_STATUS_E_FAILURE; } + +#ifdef FEATURE_ANI_LEVEL_REQUEST +QDF_STATUS wmi_unified_ani_level_cmd_send(wmi_unified_t wmi_handle, + uint32_t *freqs, + uint8_t num_freqs) +{ + if (wmi_handle->ops->send_ani_level_cmd) + return wmi_handle->ops->send_ani_level_cmd(wmi_handle, freqs, + num_freqs); + + return QDF_STATUS_E_FAILURE; +} + +QDF_STATUS wmi_unified_extract_ani_level(wmi_unified_t wmi_handle, + uint8_t *data, + struct wmi_host_ani_level_event **info, + uint32_t *num_channels) +{ + if (wmi_handle->ops->extract_ani_level) + return wmi_handle->ops->extract_ani_level(data, info, + num_channels); + + return QDF_STATUS_E_FAILURE; +} +#endif /* FEATURE_ANI_LEVEL_REQUEST */ diff --git a/wmi/src/wmi_unified_tlv.c b/wmi/src/wmi_unified_tlv.c index 3cb6bc395a..59677f39f9 100644 --- a/wmi/src/wmi_unified_tlv.c +++ b/wmi/src/wmi_unified_tlv.c @@ -12182,6 +12182,102 @@ extract_hw_mode_resp_event_status_tlv(wmi_unified_t wmi_handle, void *evt_buf, return QDF_STATUS_SUCCESS; } +#ifdef FEATURE_ANI_LEVEL_REQUEST +static QDF_STATUS send_ani_level_cmd_tlv(wmi_unified_t wmi_handle, + uint32_t *freqs, + uint8_t num_freqs) +{ + wmi_buf_t buf; + wmi_get_channel_ani_cmd_fixed_param *cmd; + QDF_STATUS ret; + uint32_t len; + A_UINT32 *chan_list; + uint8_t i, *buf_ptr; + + len = sizeof(wmi_get_channel_ani_cmd_fixed_param) + + WMI_TLV_HDR_SIZE + + num_freqs * sizeof(A_UINT32); + + buf = wmi_buf_alloc(wmi_handle, len); + if (!buf) + return QDF_STATUS_E_FAILURE; + + buf_ptr = (uint8_t *)wmi_buf_data(buf); + cmd = (wmi_get_channel_ani_cmd_fixed_param *)buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_get_channel_ani_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_get_channel_ani_cmd_fixed_param)); + + buf_ptr += sizeof(wmi_get_channel_ani_cmd_fixed_param); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, + (num_freqs * sizeof(A_UINT32))); + + chan_list = (A_UINT32 *)(buf_ptr + WMI_TLV_HDR_SIZE); + for (i = 0; i < num_freqs; i++) { + chan_list[i] = freqs[i]; + WMI_LOGD("Requesting ANI for channel[%d]", chan_list[i]); + } + + ret = wmi_unified_cmd_send(wmi_handle, buf, len, + WMI_GET_CHANNEL_ANI_CMDID); + + if (QDF_IS_STATUS_ERROR(ret)) { + WMI_LOGE("WMI_GET_CHANNEL_ANI_CMDID send error %d", ret); + wmi_buf_free(buf); + } + + return ret; +} + +static QDF_STATUS extract_ani_level_tlv(uint8_t *evt_buf, + struct wmi_host_ani_level_event **info, + uint32_t *num_freqs) +{ + WMI_GET_CHANNEL_ANI_EVENTID_param_tlvs *param_buf; + wmi_get_channel_ani_event_fixed_param *fixed_param; + wmi_channel_ani_info_tlv_param *tlv_params; + uint8_t *buf_ptr, i; + + param_buf = (WMI_GET_CHANNEL_ANI_EVENTID_param_tlvs *)evt_buf; + if (!param_buf) { + wmi_err("Invalid ani level event buffer"); + return QDF_STATUS_E_INVAL; + } + + fixed_param = + (wmi_get_channel_ani_event_fixed_param *)param_buf->fixed_param; + if (!fixed_param) { + wmi_err("Invalid fixed param"); + return QDF_STATUS_E_INVAL; + } + + buf_ptr = (uint8_t *)fixed_param; + buf_ptr += sizeof(wmi_get_channel_ani_event_fixed_param); + buf_ptr += WMI_TLV_HDR_SIZE; + + *num_freqs = param_buf->num_ani_info; + if (*num_freqs > MAX_NUM_FREQS_FOR_ANI_LEVEL) { + wmi_err("Invalid number of freqs received"); + return QDF_STATUS_E_INVAL; + } + + *info = qdf_mem_malloc(*num_freqs * + sizeof(struct wmi_host_ani_level_event)); + if (!(*info)) + return QDF_STATUS_E_NOMEM; + + tlv_params = (wmi_channel_ani_info_tlv_param *)buf_ptr; + for (i = 0; i < param_buf->num_ani_info; i++) { + (*info)[i].ani_level = tlv_params->ani_level; + (*info)[i].chan_freq = tlv_params->chan_freq; + tlv_params++; + } + + return QDF_STATUS_SUCCESS; +} +#endif /* FEATURE_ANI_LEVEL_REQUEST */ + struct wmi_ops tlv_ops = { .send_vdev_create_cmd = send_vdev_create_cmd_tlv, .send_vdev_delete_cmd = send_vdev_delete_cmd_tlv, @@ -12470,6 +12566,10 @@ struct wmi_ops tlv_ops = { .send_mws_coex_status_req_cmd = send_mws_coex_status_req_cmd_tlv, #endif .extract_hw_mode_resp_event = extract_hw_mode_resp_event_status_tlv, +#ifdef FEATURE_ANI_LEVEL_REQUEST + .send_ani_level_cmd = send_ani_level_cmd_tlv, + .extract_ani_level = extract_ani_level_tlv, +#endif /* FEATURE_ANI_LEVEL_REQUEST */ }; /** @@ -12817,6 +12917,7 @@ static void populate_tlv_events_id(uint32_t *event_ids) event_ids[wmi_motion_det_host_eventid] = WMI_MOTION_DET_HOST_EVENTID; event_ids[wmi_motion_det_base_line_host_eventid] = WMI_MOTION_DET_BASE_LINE_HOST_EVENTID; + event_ids[wmi_get_ani_level_event_id] = WMI_GET_CHANNEL_ANI_EVENTID; } /**