qcacmn: Add support in wifi pos to send wru/ftmrr frames

FTMRR and WRU frames should be sent from host and these request should
not be forwarded to FW. Add support in wifi pos to process this request
and send response to userspace.

Change-Id: I54049a1a889839e44d418ceebcca09e5092f6063
CRs-Fixed: 2500751
diff --git a/umac/wifi_pos/inc/wifi_pos_api.h b/umac/wifi_pos/inc/wifi_pos_api.h
index 9841b15..72665e1 100644
--- a/umac/wifi_pos/inc/wifi_pos_api.h
+++ b/umac/wifi_pos/inc/wifi_pos_api.h
@@ -412,4 +412,33 @@
 			struct wlan_objmgr_psoc *psoc,
 			void (*handler)(uint8_t, uint32_t, uint32_t *));
 
+/**
+ * wifi_pos_register_send_action: API to register callback to send
+ * action frames
+ * @psoc: pointer to psoc object
+ * @handler: callback to be registered
+ *
+ * Return: QDF_STATUS_SUCCESS in case of success, error codes in
+ * case of failure
+ */
+QDF_STATUS wifi_pos_register_send_action(
+				struct wlan_objmgr_psoc *psoc,
+				void (*handler)(struct wlan_objmgr_psoc *psoc,
+						uint32_t sub_type,
+						uint8_t *buf,
+						uint32_t buf_len));
+
+/**
+ * wifi_pos_send_report_resp: Send report to osif
+ * @psoc: pointer to psoc object
+ * @req_id: Request id
+ * @dest_mac: destination mac address
+ * @err_code: Error code to be sent
+ *
+ * Return: QDF_STATUS_SUCCESS in case of success, error codes in
+ * case of failure
+ */
+QDF_STATUS wifi_pos_send_report_resp(struct wlan_objmgr_psoc *psoc,
+				     int req_id, uint8_t *dest_mac,
+				     int err_code);
 #endif
diff --git a/umac/wifi_pos/src/wifi_pos_api.c b/umac/wifi_pos/src/wifi_pos_api.c
index c421fa3..cbcf95c 100644
--- a/umac/wifi_pos/src/wifi_pos_api.c
+++ b/umac/wifi_pos/src/wifi_pos_api.c
@@ -350,3 +350,31 @@
 	return QDF_STATUS_SUCCESS;
 }
 
+QDF_STATUS wifi_pos_register_send_action(
+				struct wlan_objmgr_psoc *psoc,
+				void (*handler)(struct wlan_objmgr_psoc *psoc,
+						uint32_t sub_type,
+						uint8_t *buf,
+						uint32_t buf_len))
+{
+	struct wifi_pos_psoc_priv_obj *wifi_pos_psoc;
+
+	if (!psoc) {
+		wifi_pos_err("psoc is null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	if (!handler) {
+		wifi_pos_err("Null callback");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+	wifi_pos_psoc = wifi_pos_get_psoc_priv_obj(psoc);
+	if (!wifi_pos_psoc) {
+		wifi_pos_err("wifi_pos priv obj is null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	wifi_pos_psoc->wifi_pos_send_action = handler;
+
+	return QDF_STATUS_SUCCESS;
+}
diff --git a/umac/wifi_pos/src/wifi_pos_main.c b/umac/wifi_pos/src/wifi_pos_main.c
index de59510..b298cbf 100644
--- a/umac/wifi_pos/src/wifi_pos_main.c
+++ b/umac/wifi_pos/src/wifi_pos_main.c
@@ -99,6 +99,13 @@
 	struct oem_data_req data_req;
 	struct wlan_lmac_if_wifi_pos_tx_ops *tx_ops;
 	struct wlan_objmgr_pdev *pdev;
+	struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
+				wifi_pos_get_psoc_priv_obj(psoc);
+
+	if (!wifi_pos_obj) {
+		wifi_pos_err("wifi_pos priv obj is null");
+		return QDF_STATUS_E_INVAL;
+	}
 
 	wifi_pos_debug("Received data req pid(%d), len(%d)",
 			req->pid, req->buf_len);
@@ -151,10 +158,18 @@
 		/* TBD */
 		break;
 	case TARGET_OEM_CONFIGURE_FTMRR:
-		/* TBD */
+		wifi_pos_debug("FTMRR request");
+		if (wifi_pos_obj->wifi_pos_send_action)
+			wifi_pos_obj->wifi_pos_send_action(psoc, sub_type,
+							   req->buf,
+							   req->buf_len);
 		break;
 	case TARGET_OEM_CONFIGURE_WRU:
-		/* TBD */
+		wifi_pos_debug("WRU request");
+		if (wifi_pos_obj->wifi_pos_send_action)
+			wifi_pos_obj->wifi_pos_send_action(psoc, sub_type,
+							   req->buf,
+							   req->buf_len);
 		break;
 	default:
 		wifi_pos_debug("invalid sub type or not passed");
@@ -234,6 +249,40 @@
 	return QDF_STATUS_SUCCESS;
 }
 
+QDF_STATUS wifi_pos_send_report_resp(struct wlan_objmgr_psoc *psoc,
+				     int req_id, uint8_t *dest_mac,
+				     int err_code)
+{
+	struct wifi_pos_err_msg_report err_report = {0};
+	struct wifi_pos_psoc_priv_obj *wifi_pos_obj =
+					wifi_pos_get_psoc_priv_obj(psoc);
+
+	if (!wifi_pos_obj) {
+		wifi_pos_err("wifi_pos priv obj is null");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	err_report.msg_tag_len = OEM_MSG_RSP_HEAD_TAG_ID << 16;
+	err_report.msg_tag_len |= (sizeof(err_report) -
+				   sizeof(err_report.err_rpt)) & 0x0000FFFF;
+	err_report.msg_subtype = TARGET_OEM_ERROR_REPORT_RSP;
+	err_report.req_id = req_id & 0xFFFF;
+	err_report.req_id |= ((err_code & 0xFF) << 16);
+	err_report.req_id |= (0x1 << 24);
+	err_report.time_left = 0xFFFFFFFF;
+	err_report.err_rpt.tag_len = OEM_MEAS_RSP_HEAD_TAG_ID << 16;
+	err_report.err_rpt.tag_len |=
+				(sizeof(struct wifi_pos_err_rpt)) & 0x0000FFFF;
+	memcpy(&err_report.err_rpt.dest_mac, dest_mac, QDF_MAC_ADDR_SIZE);
+
+	wifi_pos_obj->wifi_pos_send_rsp(wifi_pos_obj->app_pid,
+			ANI_MSG_OEM_DATA_RSP,
+			sizeof(err_report),
+			(uint8_t *)&err_report);
+
+	return QDF_STATUS_SUCCESS;
+}
+
 static void wifi_update_channel_bw_info(struct wlan_objmgr_psoc *psoc,
 					struct wlan_objmgr_pdev *pdev,
 					uint16_t chan,
diff --git a/umac/wifi_pos/src/wifi_pos_utils_i.h b/umac/wifi_pos/src/wifi_pos_utils_i.h
index 4c23460..c94269b 100644
--- a/umac/wifi_pos/src/wifi_pos_utils_i.h
+++ b/umac/wifi_pos/src/wifi_pos_utils_i.h
@@ -189,6 +189,42 @@
 };
 
 /**
+ * struct wifi_pos_err_rpt - Error report response for userspace.
+ * @tag_len: tlv header of the message.
+ * @info: Report info. Reserved for error report.
+ * @dest_mac: Mac address of the sta in the request.
+ * @reserved: Reserved in error report.
+ */
+struct qdf_packed wifi_pos_err_rpt {
+	uint32_t tag_len;
+	uint32_t info;
+	uint8_t  dest_mac[QDF_MAC_ADDR_SIZE + 2];
+	uint32_t reserved;
+};
+
+#define OEM_MSG_RSP_HEAD_TAG_ID 33
+#define OEM_MEAS_RSP_HEAD_TAG_ID 41
+/**
+ * struct wifi_pos_err_msg_report - Error report message
+ * @msg_tag_len: Message tlv header
+ * @msg_subtype: Message subtype
+ * @req_id: id corresponding to the request.
+ * @fragment_info: Valid only for fragments.
+ * @pdev_id: pdev_id of radion.
+ * @time_left: time left in the measurment req.
+ * @err_rpt: Error report data.
+ */
+struct qdf_packed wifi_pos_err_msg_report {
+	uint32_t msg_tag_len;
+	uint32_t msg_subtype;
+	uint32_t req_id;
+	uint32_t fragment_info;
+	uint32_t pdev_id;
+	uint32_t time_left;
+	struct wifi_pos_err_rpt err_rpt;
+};
+
+/**
  * struct wifi_pos_dma_rings_cap - capabilities requested by firmware.
  * @pdev_id: pdev_id or mac_id of ring
  * @min_num_ptr: minimum depth of ring required
@@ -306,6 +342,9 @@
 				    struct wifi_pos_req_msg *req);
 	void (*wifi_pos_send_rsp)(uint32_t, uint32_t, uint32_t, uint8_t *);
 	void (*wifi_pos_get_phy_mode)(uint8_t, uint32_t, uint32_t *);
+	void (*wifi_pos_send_action)(struct wlan_objmgr_psoc *psoc,
+				     uint32_t oem_subtype, uint8_t *buf,
+				     uint32_t len);
 };
 
 /**