Selaa lähdekoodia

qcacmn: Implement extract_comb/single_phyerr for tlv

Implement extract_comb_phyerr and extract_single_phyerr for tlv.

Change-Id: Id65809cdd05f11e39d8f5a88a3f47632e9a92b04
CRs-Fixed: 2196835
Arif Hussain 7 vuotta sitten
vanhempi
sitoutus
c5da01ead0
3 muutettua tiedostoa jossa 132 lisäystä ja 1 poistoa
  1. 2 0
      wmi/inc/wmi_unified_api.h
  2. 1 1
      wmi/src/wmi_unified_non_tlv.c
  3. 129 0
      wmi/src/wmi_unified_tlv.c

+ 2 - 0
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

+ 1 - 1
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);

+ 129 - 0
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,
 };
 
 /**