From 328db7c79c19a25a1a2ee962b7cf41a069844983 Mon Sep 17 00:00:00 2001 From: Sourav Mohapatra Date: Wed, 23 Oct 2019 10:01:18 +0530 Subject: [PATCH] qcacmn: Add support to send/receive ani level command Currently the driver doesnot support the sending and receiving of the ani level from the firmware. Add WMI and driver framework support to fetch the ani level. Change-Id: Ib8271a2b7f62bafb22429113fbfb405cc81379ed CRs-Fixed: 2554677 --- wmi/inc/wmi_unified_api.h | 27 ++++++++++ wmi/inc/wmi_unified_param.h | 14 +++++ wmi/inc/wmi_unified_priv.h | 9 ++++ wmi/src/wmi_unified_api.c | 25 +++++++++ wmi/src/wmi_unified_tlv.c | 101 ++++++++++++++++++++++++++++++++++++ 5 files changed, 176 insertions(+) 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; } /**