浏览代码

qcacmn: Handle CIR/CFR capture in WMI_OEM_RESPONSE_EVENT

Add handling of indirect data in WMI_OEM_RESPONSE_EVENTID.
This data then needs to be sent to userspace app.

Change-Id: Id1661f23ff000b33da9640cc44ea7be25e9f8dc0
CRs-Fixed: 2053958
Naveen Rawat 8 年之前
父节点
当前提交
7c3c746398
共有 3 个文件被更改,包括 144 次插入34 次删除
  1. 91 21
      target_if/wifi_pos/src/target_if_wifi_pos.c
  2. 41 9
      umac/wifi_pos/src/wifi_pos_main.c
  3. 12 4
      umac/wifi_pos/src/wifi_pos_utils_i.h

+ 91 - 21
target_if/wifi_pos/src/target_if_wifi_pos.c

@@ -90,6 +90,42 @@ static QDF_STATUS target_if_wifi_pos_replenish_ring(
 
 	return QDF_STATUS_SUCCESS;
 }
+
+static QDF_STATUS target_if_wifi_pos_get_indirect_data(
+		struct wifi_pos_psoc_priv_obj *priv_obj,
+		wmi_oem_indirect_data *indirect,
+		struct oem_data_rsp *rsp, uint32_t *cookie)
+{
+	void *paddr = NULL;
+	uint32_t addr_hi;
+	uint8_t ring_idx = 0, num_rings;
+
+	if (!indirect) {
+		target_if_debug("no indirect data. regular event received");
+		return QDF_STATUS_SUCCESS;
+	}
+
+	ring_idx = indirect->pdev_id - 1;
+	num_rings = priv_obj->num_rings;
+	if (ring_idx >= num_rings) {
+		target_if_err("incorrect pdev_id: %d", indirect->pdev_id);
+		return QDF_STATUS_E_INVAL;
+	}
+	addr_hi = (uint64_t)WMI_OEM_DMA_DATA_ADDR_HI_GET(
+						indirect->addr_hi);
+	paddr = (void *)((uint64_t)addr_hi << 32 | indirect->addr_lo);
+	*cookie = WMI_OEM_DMA_DATA_ADDR_HI_HOST_DATA_GET(
+						indirect->addr_hi);
+	rsp->vaddr = target_if_wifi_pos_vaddr_lookup(priv_obj,
+					paddr, ring_idx, *cookie);
+	rsp->dma_len = indirect->len;
+	qdf_mem_unmap_nbytes_single(NULL, (qdf_dma_addr_t)paddr,
+			QDF_DMA_FROM_DEVICE,
+			priv_obj->dma_cap[ring_idx].min_buf_size);
+
+	return QDF_STATUS_SUCCESS;
+}
+
 #else
 static QDF_STATUS target_if_wifi_pos_replenish_ring(
 			struct wifi_pos_psoc_priv_obj *priv, uint8_t ring_idx,
@@ -97,23 +133,36 @@ static QDF_STATUS target_if_wifi_pos_replenish_ring(
 {
 	return QDF_STATUS_SUCCESS;
 }
+
+static QDF_STATUS target_if_wifi_pos_get_indirect_data(
+		struct wifi_pos_psoc_priv_obj *priv_obj,
+		wmi_oem_indirect_data *indirect,
+		struct oem_data_rsp *rsp, uint32_t *cookie)
+{
+	return QDF_STATUS_SUCCESS;
+}
 #endif
 
 /**
- * wifi_pos_oem_rsp_ev_handler: handler registered with WMI_OEM_RESPONSE_EVENTID
+ * target_if_wifi_pos_oem_rsp_ev_handler: handler registered with
+ * WMI_OEM_RESPONSE_EVENTID
  * @scn: scn handle
  * @data_buf: event buffer
  * @data_len: event buffer length
  *
  * Return: status of operation
  */
-static int wifi_pos_oem_rsp_ev_handler(ol_scn_t scn,
+static int target_if_wifi_pos_oem_rsp_ev_handler(ol_scn_t scn,
 					uint8_t *data_buf,
 					uint32_t data_len)
 {
 	int ret;
+	uint8_t ring_idx = 0;
+	QDF_STATUS status;
+	uint32_t cookie = 0;
+	wmi_oem_indirect_data *indirect;
 	struct oem_data_rsp oem_rsp = {0};
-	struct wifi_pos_psoc_priv_obj *wifi_pos_psoc;
+	struct wifi_pos_psoc_priv_obj *priv_obj;
 	struct wlan_objmgr_psoc *psoc = wifi_pos_get_psoc();
 	struct wlan_lmac_if_wifi_pos_rx_ops *wifi_pos_rx_ops = NULL;
 	WMI_OEM_RESPONSE_EVENTID_param_tlvs *param_buf =
@@ -123,30 +172,51 @@ static int wifi_pos_oem_rsp_ev_handler(ol_scn_t scn,
 		wifi_pos_err("psoc is null");
 		return QDF_STATUS_NOT_INITIALIZED;
 	}
-	wifi_pos_psoc = wifi_pos_get_psoc_priv_obj(psoc);
-	if (!wifi_pos_psoc) {
-		wifi_pos_err("wifi_pos_psoc is null");
+
+	wlan_objmgr_psoc_get_ref(psoc, WLAN_WIFI_POS_ID);
+
+	priv_obj = wifi_pos_get_psoc_priv_obj(psoc);
+	if (!priv_obj) {
+		target_if_err("priv_obj is null");
+		wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_ID);
 		return QDF_STATUS_NOT_INITIALIZED;
 	}
-	qdf_spin_lock_bh(&wifi_pos_psoc->wifi_pos_lock);
-	wlan_objmgr_psoc_get_ref(psoc, WLAN_WIFI_POS_ID);
 
 	wifi_pos_rx_ops = target_if_wifi_pos_get_rxops(psoc);
-	/* this will be implemented later */
 	if (!wifi_pos_rx_ops || !wifi_pos_rx_ops->oem_rsp_event_rx) {
-		wifi_pos_err("lmac callbacks not registered");
-		ret = QDF_STATUS_NOT_INITIALIZED;
-		goto release_psoc_ref;
+		wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_ID);
+		target_if_err("lmac callbacks not registered");
+		return QDF_STATUS_NOT_INITIALIZED;
 	}
 
-	oem_rsp.rsp_len = param_buf->num_data;
-	oem_rsp.data = param_buf->data;
+	oem_rsp.rsp_len_1 = param_buf->num_data;
+	oem_rsp.data_1 = param_buf->data;
+
+	if (param_buf->num_data2) {
+		oem_rsp.rsp_len_2 = param_buf->num_data2;
+		oem_rsp.data_2 = param_buf->data2;
+	}
+
+	indirect = (wmi_oem_indirect_data *)param_buf->indirect_data;
+	status = target_if_wifi_pos_get_indirect_data(priv_obj, indirect,
+						      &oem_rsp, &cookie);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		target_if_err("get indirect data failed status: %d", status);
+		wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_ID);
+		return QDF_STATUS_E_INVAL;
+	}
 
 	ret = wifi_pos_rx_ops->oem_rsp_event_rx(psoc, &oem_rsp);
+	if (indirect)
+		ring_idx = indirect->pdev_id - 1;
+	status = target_if_wifi_pos_replenish_ring(priv_obj, ring_idx,
+					oem_rsp.vaddr, cookie);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		target_if_err("replenish failed status: %d", status);
+		ret = QDF_STATUS_E_FAILURE;
+	}
 
-release_psoc_ref:
 	wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_ID);
-	qdf_spin_unlock_bh(&wifi_pos_psoc->wifi_pos_lock);
 
 	return ret;
 }
@@ -278,8 +348,8 @@ QDF_STATUS target_if_wifi_pos_register_events(struct wlan_objmgr_psoc *psoc)
 
 	ret = wmi_unified_register_event_handler(psoc->tgt_if_handle,
 					WMI_OEM_RESPONSE_EVENTID,
-					wifi_pos_oem_rsp_ev_handler,
-					WMI_RX_UMAC_CTX);
+					target_if_wifi_pos_oem_rsp_ev_handler,
+					WMI_RX_WORK_CTX);
 	if (ret) {
 		wifi_pos_err("register_event_handler failed: err %d", ret);
 		return QDF_STATUS_E_INVAL;
@@ -288,7 +358,7 @@ QDF_STATUS target_if_wifi_pos_register_events(struct wlan_objmgr_psoc *psoc)
 	ret = wmi_unified_register_event_handler(psoc->tgt_if_handle,
 					wmi_oem_cap_event_id,
 					wifi_pos_oem_cap_ev_handler,
-					WMI_RX_UMAC_CTX);
+					WMI_RX_WORK_CTX);
 	if (ret) {
 		wifi_pos_err("register_event_handler failed: err %d", ret);
 		return QDF_STATUS_E_INVAL;
@@ -297,7 +367,7 @@ QDF_STATUS target_if_wifi_pos_register_events(struct wlan_objmgr_psoc *psoc)
 	ret = wmi_unified_register_event_handler(psoc->tgt_if_handle,
 					wmi_oem_meas_report_event_id,
 					wifi_pos_oem_meas_rpt_ev_handler,
-					WMI_RX_UMAC_CTX);
+					WMI_RX_WORK_CTX);
 	if (ret) {
 		wifi_pos_err("register_event_handler failed: err %d", ret);
 		return QDF_STATUS_E_INVAL;
@@ -306,7 +376,7 @@ QDF_STATUS target_if_wifi_pos_register_events(struct wlan_objmgr_psoc *psoc)
 	ret = wmi_unified_register_event_handler(psoc->tgt_if_handle,
 					wmi_oem_report_event_id,
 					wifi_pos_oem_err_rpt_ev_handler,
-					WMI_RX_UMAC_CTX);
+					WMI_RX_WORK_CTX);
 	if (ret) {
 		wifi_pos_err("register_event_handler failed: err %d", ret);
 		return QDF_STATUS_E_INVAL;

+ 41 - 9
umac/wifi_pos/src/wifi_pos_main.c

@@ -465,20 +465,52 @@ QDF_STATUS  wifi_pos_psoc_obj_destroyed_notification(
 int wifi_pos_oem_rsp_handler(struct wlan_objmgr_psoc *psoc,
 			     struct oem_data_rsp *oem_rsp)
 {
-	struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
+	uint32_t len;
+	uint8_t *data;
+	uint32_t app_pid;
+	struct wifi_pos_psoc_priv_obj *priv =
 					wifi_pos_get_psoc_priv_obj(psoc);
-	/* handle oem event here */
-	if (oem_rsp->rsp_len > OEM_DATA_RSP_SIZE) {
+	void (*wifi_pos_send_rsp)(uint32_t, uint32_t, uint32_t, uint8_t *);
+
+	if (!priv) {
+		wifi_pos_err("private object is NULL");
+		return -EINVAL;
+	}
+
+	qdf_spin_lock_bh(&priv->wifi_pos_lock);
+	app_pid = priv->app_pid;
+	wifi_pos_send_rsp = priv->wifi_pos_send_rsp;
+	qdf_spin_unlock_bh(&priv->wifi_pos_lock);
+
+	len = oem_rsp->rsp_len_1 + oem_rsp->rsp_len_2 + oem_rsp->dma_len;
+	if (oem_rsp->rsp_len_1 > OEM_DATA_RSP_SIZE ||
+			oem_rsp->rsp_len_2 > OEM_DATA_RSP_SIZE) {
 		wifi_pos_err("invalid length of Oem Data response");
 		return -EINVAL;
 	}
 
-	wifi_pos_debug("sending oem data rsp, len: %d to pid: %d",
-			oem_rsp->rsp_len, wifi_pos_obj->app_pid);
-	wifi_pos_obj->wifi_pos_send_rsp(wifi_pos_obj->app_pid,
-					ANI_MSG_OEM_DATA_RSP,
-					oem_rsp->rsp_len,
-					oem_rsp->data);
+	wifi_pos_debug("oem data rsp, len: %d to pid: %d", len, app_pid);
+
+	if (oem_rsp->rsp_len_2 + oem_rsp->dma_len) {
+		/* stitch togther the msg data_1 + CIR/CFR + data_2 */
+		data = qdf_mem_malloc(len);
+		if (!data) {
+			wifi_pos_err("malloc failed");
+			return -ENOMEM;
+		}
+		qdf_mem_copy(data, oem_rsp->data_1, oem_rsp->rsp_len_1);
+		qdf_mem_copy(&data[oem_rsp->rsp_len_1],
+			     oem_rsp->vaddr, oem_rsp->dma_len);
+		qdf_mem_copy(&data[oem_rsp->rsp_len_1 + oem_rsp->dma_len],
+			     oem_rsp->data_2, oem_rsp->rsp_len_2);
+
+		wifi_pos_send_rsp(app_pid, ANI_MSG_OEM_DATA_RSP, len, data);
+		qdf_mem_free(data);
+	} else {
+		wifi_pos_send_rsp(app_pid, ANI_MSG_OEM_DATA_RSP,
+				  oem_rsp->rsp_len_1, oem_rsp->data_1);
+	}
+
 	return 0;
 }
 

+ 12 - 4
umac/wifi_pos/src/wifi_pos_utils_i.h

@@ -106,13 +106,21 @@ struct oem_data_req {
 
 /**
  * struct oem_data_rsp - response from firmware to data request sent earlier
- * @data_len: len of data
- * @data: buffer containing data
+ * @rsp_len_1: len of data_1
+ * @data_1: first part of payload
+ * @rsp_len_2: len of data_2
+ * @data_2: second part of payload
+ * @dma_len: len of DMAed data
+ * @vaddr: virtual address of DMA data start
  *
  */
 struct oem_data_rsp {
-	uint32_t rsp_len;
-	uint8_t *data;
+	uint32_t rsp_len_1;
+	uint8_t *data_1;
+	uint32_t rsp_len_2;
+	uint8_t *data_2;
+	uint32_t dma_len;
+	void *vaddr;
 };
 
 /**