Merge "qcacmn: Add support in wifi pos to send wru/ftmrr frames"
diff --git a/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h b/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h
index 4062353..4d8a42d 100644
--- a/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h
+++ b/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h
@@ -982,6 +982,8 @@
 			struct cur_regdmn_info *cur_regdmn);
 	QDF_STATUS (*reg_enable_dfs_channels)(struct wlan_objmgr_pdev *pdev,
 					      bool dfs_enable);
+	QDF_STATUS (*reg_modify_pdev_chan_range)(struct
+						 wlan_objmgr_pdev *pdev);
 };
 
 #ifdef CONVERGED_P2P_ENABLE
@@ -1253,8 +1255,10 @@
  * @dfs_dfs_cac_complete_ind:         Process cac complete indication.
  * @dfs_agile_precac_start:           Initiate Agile PreCAC run.
  * @dfs_set_agile_precac_state:       Set agile precac state.
+ * @dfs_reset_adfs_config:            Reset agile dfs variables.
  * @dfs_dfs_ocac_complete_ind:        Process offchan cac complete indication.
  * @dfs_stop:                         Clear dfs timers.
+ * @dfs_reinit_timers:                Reinitialize DFS timers.
  * @dfs_enable_stadfs:                Enable/Disable STADFS capability.
  * @dfs_is_stadfs_enabled:            Get STADFS capability value.
  * @dfs_process_phyerr_filter_offload:Process radar event.
@@ -1308,6 +1312,7 @@
 	QDF_STATUS (*dfs_agile_precac_start)(struct wlan_objmgr_pdev *pdev);
 	QDF_STATUS (*dfs_set_agile_precac_state)(struct wlan_objmgr_pdev *pdev,
 						 int agile_precac_state);
+	QDF_STATUS (*dfs_reset_adfs_config)(struct wlan_objmgr_psoc *psoc);
 	QDF_STATUS
 	(*dfs_dfs_ocac_complete_ind)(struct wlan_objmgr_pdev *pdev,
 				     struct vdev_adfs_complete_status *ocac_st);
@@ -1348,6 +1353,7 @@
 			uint32_t vdev_id);
 #endif
 	QDF_STATUS (*dfs_stop)(struct wlan_objmgr_pdev *pdev);
+	QDF_STATUS (*dfs_reinit_timers)(struct wlan_objmgr_pdev *pdev);
 	void (*dfs_enable_stadfs)(struct wlan_objmgr_pdev *pdev, bool val);
 	bool (*dfs_is_stadfs_enabled)(struct wlan_objmgr_pdev *pdev);
 	QDF_STATUS (*dfs_process_phyerr_filter_offload)(
diff --git a/umac/global_umac_dispatcher/lmac_if/src/wlan_lmac_if.c b/umac/global_umac_dispatcher/lmac_if/src/wlan_lmac_if.c
index c4d8433..f8a7d70 100644
--- a/umac/global_umac_dispatcher/lmac_if/src/wlan_lmac_if.c
+++ b/umac/global_umac_dispatcher/lmac_if/src/wlan_lmac_if.c
@@ -323,6 +323,9 @@
 
 	rx_ops->reg_rx_ops.reg_enable_dfs_channels =
 		ucfg_reg_enable_dfs_channels;
+
+	rx_ops->reg_rx_ops.reg_modify_pdev_chan_range =
+		wlan_reg_modify_pdev_chan_range;
 }
 
 #ifdef CONVERGED_P2P_ENABLE
@@ -394,6 +397,7 @@
 		tgt_dfs_set_agile_precac_state;
 	dfs_rx_ops->dfs_start_precac_timer = utils_dfs_start_precac_timer;
 	dfs_rx_ops->dfs_cancel_precac_timer = utils_dfs_cancel_precac_timer;
+	dfs_rx_ops->dfs_reset_adfs_config = ucfg_dfs_reset_agile_config;
 	dfs_rx_ops->dfs_override_precac_timeout =
 		ucfg_dfs_override_precac_timeout;
 	dfs_rx_ops->dfs_set_precac_enable = ucfg_dfs_set_precac_enable;
@@ -405,6 +409,7 @@
 	dfs_rx_ops->dfs_dfs_cac_complete_ind = tgt_dfs_cac_complete;
 	dfs_rx_ops->dfs_dfs_ocac_complete_ind = tgt_dfs_ocac_complete;
 	dfs_rx_ops->dfs_stop = tgt_dfs_stop;
+	dfs_rx_ops->dfs_reinit_timers = ucfg_dfs_reinit_timers;
 	dfs_rx_ops->dfs_enable_stadfs = tgt_dfs_enable_stadfs;
 	dfs_rx_ops->dfs_is_stadfs_enabled = tgt_dfs_is_stadfs_enabled;
 	dfs_rx_ops->dfs_process_phyerr_filter_offload =
diff --git a/umac/regulatory/core/src/reg_services_common.c b/umac/regulatory/core/src/reg_services_common.c
index c10a431..8cf19a0 100644
--- a/umac/regulatory/core/src/reg_services_common.c
+++ b/umac/regulatory/core/src/reg_services_common.c
@@ -2023,3 +2023,87 @@
 
 	return reg_en302_502_regdmn(cur_reg_dmn.regdmn_pair_id);
 }
+
+QDF_STATUS reg_modify_pdev_chan_range(struct wlan_objmgr_pdev *pdev)
+{
+	struct wlan_regulatory_pdev_priv_obj *pdev_priv_obj;
+	struct wlan_regulatory_psoc_priv_obj *psoc_priv_obj;
+	struct wlan_objmgr_psoc *psoc;
+	struct wlan_lmac_if_reg_tx_ops *reg_tx_ops;
+	struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap_ptr;
+	uint32_t cnt;
+	uint32_t pdev_id;
+	enum direction dir;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
+	pdev_priv_obj = reg_get_pdev_obj(pdev);
+	if (!IS_VALID_PDEV_REG_OBJ(pdev_priv_obj)) {
+		reg_err("pdev reg component is NULL");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	psoc = wlan_pdev_get_psoc(pdev);
+	if (!psoc) {
+		reg_err("psoc is NULL");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	psoc_priv_obj = reg_get_psoc_obj(psoc);
+	if (!IS_VALID_PSOC_REG_OBJ(psoc_priv_obj)) {
+		reg_err("psoc reg component is NULL");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	reg_cap_ptr = psoc_priv_obj->reg_cap;
+
+	for (cnt = 0; cnt < PSOC_MAX_PHY_REG_CAP; cnt++) {
+		if (!reg_cap_ptr) {
+			qdf_mem_free(pdev_priv_obj);
+			reg_err("reg cap ptr is NULL");
+			return QDF_STATUS_E_FAULT;
+		}
+
+		if (reg_cap_ptr->phy_id == pdev_id)
+			break;
+		reg_cap_ptr++;
+	}
+
+	if (cnt == PSOC_MAX_PHY_REG_CAP) {
+		qdf_mem_free(pdev_priv_obj);
+		reg_err("extended capabilities not found for pdev");
+		return QDF_STATUS_E_FAULT;
+	}
+
+	if (psoc_priv_obj->offload_enabled) {
+		dir = NORTHBOUND;
+	} else {
+		dir = SOUTHBOUND;
+	}
+
+	pdev_priv_obj->range_2g_low = reg_cap_ptr->low_2ghz_chan;
+	pdev_priv_obj->range_2g_high = reg_cap_ptr->high_2ghz_chan;
+	pdev_priv_obj->range_5g_low = reg_cap_ptr->low_5ghz_chan;
+	pdev_priv_obj->range_5g_high = reg_cap_ptr->high_5ghz_chan;
+	pdev_priv_obj->wireless_modes = reg_cap_ptr->wireless_modes;
+
+	reg_compute_pdev_current_chan_list(pdev_priv_obj);
+
+	reg_tx_ops = reg_get_psoc_tx_ops(psoc);
+
+	/* Fill the ic channel list with the updated current channel
+	 * chan list.
+	 */
+	if (reg_tx_ops->fill_umac_legacy_chanlist) {
+	    reg_tx_ops->fill_umac_legacy_chanlist(pdev,
+						  pdev_priv_obj->cur_chan_list);
+
+	} else {
+		if (dir == NORTHBOUND)
+			status = reg_send_scheduler_msg_nb(psoc, pdev);
+		else
+			status = reg_send_scheduler_msg_sb(psoc, pdev);
+	}
+
+	return status;
+}
diff --git a/umac/regulatory/core/src/reg_services_common.h b/umac/regulatory/core/src/reg_services_common.h
index d2ed228..52df9be 100644
--- a/umac/regulatory/core/src/reg_services_common.h
+++ b/umac/regulatory/core/src/reg_services_common.h
@@ -514,4 +514,13 @@
  * Return: True if en302_502 is applicable, else false.
  */
 bool reg_is_regdmn_en302502_applicable(struct wlan_objmgr_pdev *pdev);
+
+/**
+ * reg_modify_pdev_chan_range() - Compute current channel list
+ * in accordance with the modified reg caps.
+ * @pdev: The physical dev for which channel list must be built.
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS reg_modify_pdev_chan_range(struct wlan_objmgr_pdev *pdev);
 #endif
diff --git a/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h b/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h
index f7da9e3..b3a7d32 100644
--- a/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h
+++ b/umac/regulatory/dispatcher/inc/wlan_reg_services_api.h
@@ -703,4 +703,13 @@
  * False: otherwise.
  */
 bool wlan_reg_is_regdmn_en302502_applicable(struct wlan_objmgr_pdev *pdev);
+
+/**
+ * wlan_reg_modify_pdev_chan_range() - Compute current channel list for the
+ * modified channel range in the regcap.
+ * @pdev: pointer to wlan_objmgr_pdev.
+ *
+ * Return : QDF_STATUS
+ */
+QDF_STATUS wlan_reg_modify_pdev_chan_range(struct wlan_objmgr_pdev *pdev);
 #endif
diff --git a/umac/regulatory/dispatcher/src/wlan_reg_services_api.c b/umac/regulatory/dispatcher/src/wlan_reg_services_api.c
index 67e5d74..5b91725 100644
--- a/umac/regulatory/dispatcher/src/wlan_reg_services_api.c
+++ b/umac/regulatory/dispatcher/src/wlan_reg_services_api.c
@@ -713,3 +713,14 @@
 {
 	return reg_is_regdmn_en302502_applicable(pdev);
 }
+
+/**
+ * wlan_reg_modify_pdev_chan_range() - Compute current channel list for the
+ * modified regcap.
+ * @pdev: pointer to struct wlan_objmgr_pdev
+ *
+ */
+QDF_STATUS wlan_reg_modify_pdev_chan_range(struct wlan_objmgr_pdev *pdev)
+{
+	return reg_modify_pdev_chan_range(pdev);
+}
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);
 };
 
 /**