qcacmn: Add OEM DATA vendor command support

This command is used to send OEM data binary blobs
from application/service to firmware.

Change-Id: Id806638bf8c53c65b32177969d965290da5701b9
CRs-Fixed: 2477337
diff --git a/target_if/wifi_pos/src/target_if_wifi_pos.c b/target_if/wifi_pos/src/target_if_wifi_pos.c
index 239bd08..73b6395 100644
--- a/target_if/wifi_pos/src/target_if_wifi_pos.c
+++ b/target_if/wifi_pos/src/target_if_wifi_pos.c
@@ -260,7 +260,7 @@
 
 /**
  * wifi_pos_oem_data_req() - start OEM data request to target
- * @wma_handle: wma handle
+ * @psoc: the pointer to psoc object manager
  * @req: start request params
  *
  * Return: QDF_STATUS
diff --git a/wmi/inc/wmi_unified_api.h b/wmi/inc/wmi_unified_api.h
index 12239a8..ba10fb6 100644
--- a/wmi/inc/wmi_unified_api.h
+++ b/wmi/inc/wmi_unified_api.h
@@ -1233,10 +1233,13 @@
 #endif
 
 /**
- * wmi_unified_start_oem_data_cmd() - start OEM data request to target
+ * wmi_unified_start_oem_data_cmd() - start oem data request to target
  * @wmi_handle: wmi handle
- * @data_len: length of OEM data
- * @data: OEM data
+ * @data_len: the length of @data
+ * @data: the pointer to data buf
+ *
+ * This is legacy api for oem data request, using wmi command
+ * WMI_OEM_REQ_CMDID.
  *
  * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure
  */
@@ -1244,6 +1247,20 @@
 					  uint32_t data_len,
 					  uint8_t *data);
 
+#ifdef FEATURE_OEM_DATA
+/**
+ * wmi_unified_start_oemv2_data_cmd() - start oem data cmd to target
+ * @wmi_handle: wmi handle
+ * @params: oem data params
+ *
+ * This is common api for oem data, using wmi command WMI_OEM_DATA_CMDID.
+ *
+ * Return: QDF_STATUS_SUCCESS on success and QDF_STATUS_E_FAILURE for failure
+ */
+QDF_STATUS wmi_unified_start_oemv2_data_cmd(wmi_unified_t wmi_handle,
+					    struct oem_data *params);
+#endif
+
 /**
  * wmi_unified_dfs_phyerr_filter_offload_en_cmd() - enable dfs phyerr filter
  * @wmi_handle: wmi handle
diff --git a/wmi/inc/wmi_unified_param.h b/wmi/inc/wmi_unified_param.h
index 8bf94e8..6dc67a0 100644
--- a/wmi/inc/wmi_unified_param.h
+++ b/wmi/inc/wmi_unified_param.h
@@ -656,6 +656,20 @@
 	uint8_t  reg_class_id;
 };
 
+#ifdef FEATURE_OEM_DATA
+/**
+ * struct oem_data - oem data to be sent to firmware
+ * @vdev_id: Unique identifier assigned to the vdev
+ * @data_len: len of data
+ * @data: the pointer to the buffer containing data
+ */
+struct oem_data {
+	uint8_t vdev_id;
+	size_t data_len;
+	uint8_t *data;
+};
+#endif
+
 /**
  * struct mac_ssid - mac ssid structure
  * @length:
diff --git a/wmi/inc/wmi_unified_priv.h b/wmi/inc/wmi_unified_priv.h
index 3eaed8f..ba6e650 100644
--- a/wmi/inc/wmi_unified_priv.h
+++ b/wmi/inc/wmi_unified_priv.h
@@ -805,8 +805,13 @@
 #endif
 
 QDF_STATUS (*send_start_oem_data_cmd)(wmi_unified_t wmi_handle,
-			  uint32_t data_len,
-			  uint8_t *data);
+				      uint32_t data_len,
+				      uint8_t *data);
+
+#ifdef FEATURE_OEM_DATA
+QDF_STATUS (*send_start_oemv2_data_cmd)(wmi_unified_t wmi_handle,
+					struct oem_data *params);
+#endif
 
 QDF_STATUS
 (*send_dfs_phyerr_filter_offload_en_cmd)(wmi_unified_t wmi_handle,
diff --git a/wmi/src/wmi_unified_api.c b/wmi/src/wmi_unified_api.c
index d653cc5..66a758a 100644
--- a/wmi/src/wmi_unified_api.c
+++ b/wmi/src/wmi_unified_api.c
@@ -934,7 +934,7 @@
 wmi_unified_oem_dma_ring_cfg(wmi_unified_t wmi_handle,
 			     wmi_oem_dma_ring_cfg_req_fixed_param *cfg)
 {
-	if (wmi_handle->ops->send_start_oem_data_cmd)
+	if (wmi_handle->ops->send_oem_dma_cfg_cmd)
 		return wmi_handle->ops->send_oem_dma_cfg_cmd(wmi_handle, cfg);
 
 	return QDF_STATUS_E_FAILURE;
@@ -947,11 +947,24 @@
 {
 	if (wmi_handle->ops->send_start_oem_data_cmd)
 		return wmi_handle->ops->send_start_oem_data_cmd(wmi_handle,
-			    data_len, data);
+								data_len,
+								data);
 
 	return QDF_STATUS_E_FAILURE;
 }
 
+#ifdef FEATURE_OEM_DATA
+QDF_STATUS wmi_unified_start_oemv2_data_cmd(wmi_unified_t wmi_handle,
+					    struct oem_data *params)
+{
+	if (wmi_handle->ops->send_start_oemv2_data_cmd)
+		return wmi_handle->ops->send_start_oemv2_data_cmd(wmi_handle,
+								  params);
+
+	return QDF_STATUS_E_FAILURE;
+}
+#endif
+
 QDF_STATUS
 wmi_unified_dfs_phyerr_filter_offload_en_cmd(wmi_unified_t wmi_handle,
 					     bool dfs_phyerr_filter_offload)
diff --git a/wmi/src/wmi_unified_tlv.c b/wmi/src/wmi_unified_tlv.c
index 1a16bb7..790fffa 100644
--- a/wmi/src/wmi_unified_tlv.c
+++ b/wmi/src/wmi_unified_tlv.c
@@ -5292,13 +5292,14 @@
 /**
  * send_start_oem_data_cmd_tlv() - start OEM data request to target
  * @wmi_handle: wmi handle
- * @startOemDataReq: start request params
+ * @data_len: the length of @data
+ * @data: the pointer to data buf
  *
  * Return: CDF status
  */
 static QDF_STATUS send_start_oem_data_cmd_tlv(wmi_unified_t wmi_handle,
-			  uint32_t data_len,
-			  uint8_t *data)
+					      uint32_t data_len,
+					      uint8_t *data)
 {
 	wmi_buf_t buf;
 	uint8_t *cmd;
@@ -5332,6 +5333,68 @@
 	return ret;
 }
 
+#ifdef FEATURE_OEM_DATA
+/**
+ * send_start_oemv2_data_cmd_tlv() - start OEM data to target
+ * @wmi_handle: wmi handle
+ * @oem_data: the pointer to oem data
+ *
+ * Return: QDF status
+ */
+static QDF_STATUS send_start_oemv2_data_cmd_tlv(wmi_unified_t wmi_handle,
+						struct oem_data *oem_data)
+{
+	QDF_STATUS ret;
+	wmi_oem_data_cmd_fixed_param *cmd;
+	wmi_buf_t buf;
+	uint16_t len = sizeof(*cmd);
+	uint16_t oem_data_len_aligned;
+	uint8_t *buf_ptr;
+
+	if (!oem_data || !oem_data->data) {
+		wmi_err_rl("oem data is not valid");
+		return QDF_STATUS_E_FAILURE;
+	}
+	oem_data_len_aligned = roundup(oem_data->data_len, sizeof(uint32_t));
+	if (oem_data_len_aligned < oem_data->data_len) {
+		wmi_err_rl("integer overflow while rounding up data_len");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	if (oem_data_len_aligned > WMI_SVC_MSG_MAX_SIZE - WMI_TLV_HDR_SIZE) {
+		wmi_err_rl("wmi_max_msg_size overflow for given data_len");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	len += WMI_TLV_HDR_SIZE + oem_data_len_aligned;
+	buf = wmi_buf_alloc(wmi_handle, len);
+	if (!buf)
+		return QDF_STATUS_E_NOMEM;
+
+	buf_ptr = (uint8_t *)wmi_buf_data(buf);
+	cmd = (wmi_oem_data_cmd_fixed_param *)buf_ptr;
+	WMITLV_SET_HDR(&cmd->tlv_header,
+		       WMITLV_TAG_STRUC_wmi_oem_data_cmd_fixed_param,
+		       WMITLV_GET_STRUCT_TLVLEN(wmi_oem_data_cmd_fixed_param));
+
+	cmd->vdev_id = oem_data->vdev_id;
+	cmd->data_len = oem_data->data_len;
+	buf_ptr += sizeof(*cmd);
+	WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, oem_data_len_aligned);
+	buf_ptr += WMI_TLV_HDR_SIZE;
+	qdf_mem_copy(buf_ptr, oem_data->data, oem_data->data_len);
+
+	wmi_mtrace(WMI_OEM_DATA_CMDID, NO_SESSION, 0);
+	ret = wmi_unified_cmd_send(wmi_handle, buf, len, WMI_OEM_DATA_CMDID);
+	if (QDF_IS_STATUS_ERROR(ret)) {
+		wmi_err_rl("Failed with ret = %d", ret);
+		wmi_buf_free(buf);
+	}
+
+	return ret;
+}
+#endif
+
 /**
  * send_dfs_phyerr_filter_offload_en_cmd_tlv() - enable dfs phyerr filter
  * @wmi_handle: wmi handle
@@ -11670,6 +11733,9 @@
 #endif
 	.send_csa_offload_enable_cmd = send_csa_offload_enable_cmd_tlv,
 	.send_start_oem_data_cmd = send_start_oem_data_cmd_tlv,
+#ifdef FEATURE_OEM_DATA
+	.send_start_oemv2_data_cmd = send_start_oemv2_data_cmd_tlv,
+#endif
 #ifdef WLAN_FEATURE_CIF_CFR
 	.send_oem_dma_cfg_cmd = send_oem_dma_cfg_cmd_tlv,
 #endif