From c5da01ead09a0bf03cc3abbfa5319d85e4583256 Mon Sep 17 00:00:00 2001 From: Arif Hussain Date: Thu, 1 Mar 2018 14:40:59 -0800 Subject: [PATCH] qcacmn: Implement extract_comb/single_phyerr for tlv Implement extract_comb_phyerr and extract_single_phyerr for tlv. Change-Id: Id65809cdd05f11e39d8f5a88a3f47632e9a92b04 CRs-Fixed: 2196835 --- wmi/inc/wmi_unified_api.h | 2 + wmi/src/wmi_unified_non_tlv.c | 2 +- wmi/src/wmi_unified_tlv.c | 129 ++++++++++++++++++++++++++++++++++ 3 files changed, 132 insertions(+), 1 deletion(-) diff --git a/wmi/inc/wmi_unified_api.h b/wmi/inc/wmi_unified_api.h index 7a6a9f4204..1789bc7f25 100644 --- a/wmi/inc/wmi_unified_api.h +++ b/wmi/inc/wmi_unified_api.h @@ -86,6 +86,8 @@ typedef qdf_nbuf_t wmi_buf_t; #define WMI_LOGA(args ...) #endif +#define PHYERROR_MAX_BUFFER_LENGTH 0x7F000000 + struct wmi_soc; /** * struct wmi_ops - service callbacks to upper layer diff --git a/wmi/src/wmi_unified_non_tlv.c b/wmi/src/wmi_unified_non_tlv.c index a7baa92844..84a7b31de0 100644 --- a/wmi/src/wmi_unified_non_tlv.c +++ b/wmi/src/wmi_unified_non_tlv.c @@ -7285,7 +7285,7 @@ static QDF_STATUS extract_single_phyerr_non_tlv(wmi_unified_t wmi_handle, * * If "int" is 64 bits then this becomes a moot point. */ - if (ev->hdr.buf_len > 0x7f000000) { + if (ev->hdr.buf_len > PHYERROR_MAX_BUFFER_LENGTH) { qdf_print("%s: buf_len is garbage? (0x%x\n)\n", __func__, ev->hdr.buf_len); diff --git a/wmi/src/wmi_unified_tlv.c b/wmi/src/wmi_unified_tlv.c index df112e6c4d..7389ee41e1 100644 --- a/wmi/src/wmi_unified_tlv.c +++ b/wmi/src/wmi_unified_tlv.c @@ -22218,6 +22218,133 @@ static QDF_STATUS extract_obss_color_collision_info_tlv(uint8_t *evt_buf, return QDF_STATUS_SUCCESS; } +/* + * extract_comb_phyerr_tlv() - extract comb phy error from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @datalen: data length of event buffer + * @buf_offset: Pointer to hold value of current event buffer offset + * post extraction + * @phyerr: Pointer to hold phyerr + * + * Return: QDF_STATUS + */ +static QDF_STATUS extract_comb_phyerr_tlv(wmi_unified_t wmi_handle, + void *evt_buf, + uint16_t datalen, + uint16_t *buf_offset, + wmi_host_phyerr_t *phyerr) +{ + WMI_PHYERR_EVENTID_param_tlvs *param_tlvs; + wmi_comb_phyerr_rx_hdr *pe_hdr; + + param_tlvs = (WMI_PHYERR_EVENTID_param_tlvs *)evt_buf; + if (!param_tlvs) { + WMI_LOGD("%s: Received null data from FW", __func__); + return QDF_STATUS_E_FAILURE; + } + + pe_hdr = param_tlvs->hdr; + if (!pe_hdr) { + WMI_LOGD("%s: Received Data PE Header is NULL", __func__); + return QDF_STATUS_E_FAILURE; + } + + /* Ensure it's at least the size of the header */ + if (datalen < sizeof(*pe_hdr)) { + WMI_LOGD("%s: Expected minimum size %zu, received %d", + __func__, sizeof(*pe_hdr), datalen); + return QDF_STATUS_E_FAILURE; + } + + phyerr->pdev_id = wmi_handle->ops-> + convert_pdev_id_target_to_host(pe_hdr->pdev_id); + phyerr->tsf64 = pe_hdr->tsf_l32; + phyerr->tsf64 |= (((uint64_t)pe_hdr->tsf_u32) << 32); + phyerr->bufp = param_tlvs->bufp; + phyerr->buf_len = pe_hdr->buf_len; + phyerr->phy_err_mask0 = pe_hdr->rsPhyErrMask0; + phyerr->phy_err_mask1 = pe_hdr->rsPhyErrMask1; + *buf_offset = sizeof(*pe_hdr) + sizeof(uint32_t); + + return QDF_STATUS_SUCCESS; +} + +/** + * extract_single_phyerr_tlv() - extract single phy error from event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @datalen: data length of event buffer + * @buf_offset: Pointer to hold value of current event buffer offset + * post extraction + * @phyerr: Pointer to hold phyerr + * + * Return: QDF_STATUS + */ +static QDF_STATUS extract_single_phyerr_tlv(wmi_unified_t wmi_handle, + void *evt_buf, + uint16_t datalen, + uint16_t *buf_offset, + wmi_host_phyerr_t *phyerr) +{ + wmi_single_phyerr_rx_event *ev; + uint16_t n = *buf_offset; + uint8_t *data = (uint8_t *)evt_buf; + + if (n < datalen) { + if ((datalen - n) < sizeof(ev->hdr)) { + WMI_LOGD("%s: Not enough space. len=%d, n=%d, hdr=%zu", + __func__, datalen, n, sizeof(ev->hdr)); + return QDF_STATUS_E_FAILURE; + } + + /* + * Obtain a pointer to the beginning of the current event. + * data[0] is the beginning of the WMI payload. + */ + ev = (wmi_single_phyerr_rx_event *)&data[n]; + + /* + * Sanity check the buffer length of the event against + * what we currently have. + * + * Since buf_len is 32 bits, we check if it overflows + * a large 32 bit value. It's not 0x7fffffff because + * we increase n by (buf_len + sizeof(hdr)), which would + * in itself cause n to overflow. + * + * If "int" is 64 bits then this becomes a moot point. + */ + if (ev->hdr.buf_len > PHYERROR_MAX_BUFFER_LENGTH) { + WMI_LOGD("%s: buf_len is garbage 0x%x", + __func__, ev->hdr.buf_len); + return QDF_STATUS_E_FAILURE; + } + + if ((n + ev->hdr.buf_len) > datalen) { + WMI_LOGD("%s: len exceeds n=%d, buf_len=%d, datalen=%d", + __func__, n, ev->hdr.buf_len, datalen); + return QDF_STATUS_E_FAILURE; + } + + phyerr->phy_err_code = WMI_UNIFIED_PHYERRCODE_GET(&ev->hdr); + phyerr->tsf_timestamp = ev->hdr.tsf_timestamp; + phyerr->bufp = &ev->bufp[0]; + phyerr->buf_len = ev->hdr.buf_len; + phyerr->rf_info.rssi_comb = WMI_UNIFIED_RSSI_COMB_GET(&ev->hdr); + + /* + * Advance the buffer pointer to the next PHY error. + * buflen is the length of this payload, so we need to + * advance past the current header _AND_ the payload. + */ + n += sizeof(*ev) + ev->hdr.buf_len; + } + *buf_offset = n; + + return QDF_STATUS_SUCCESS; +} + struct wmi_ops tlv_ops = { .send_vdev_create_cmd = send_vdev_create_cmd_tlv, .send_vdev_delete_cmd = send_vdev_delete_cmd_tlv, @@ -22695,6 +22822,8 @@ struct wmi_ops tlv_ops = { send_obss_color_collision_cfg_cmd_tlv, .extract_obss_color_collision_info = extract_obss_color_collision_info_tlv, + .extract_comb_phyerr = extract_comb_phyerr_tlv, + .extract_single_phyerr = extract_single_phyerr_tlv, }; /**