qcacld-3.0: Allocate and initialize the FST for FISA

Add FST setup functions for allocating SW and DDR HW FT.

Change-Id: I13e7d5a40c7440f95d2308e0da5a883557b6b399
CRs-Fixed: 2600268
diff --git a/core/dp/txrx3.0/dp_rx_fst.c b/core/dp/txrx3.0/dp_rx_fst.c
new file mode 100644
index 0000000..30b7fa5
--- /dev/null
+++ b/core/dp/txrx3.0/dp_rx_fst.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "dp_types.h"
+#include "qdf_mem.h"
+#include "qdf_nbuf.h"
+#include "cfg_dp.h"
+#include "wlan_cfg.h"
+#include "dp_types.h"
+#include "hal_rx_flow.h"
+#include "dp_htt.h"
+#include "dp_internal.h"
+
+#ifdef WLAN_SUPPORT_RX_FISA
+
+void dp_rx_dump_fisa_table(struct dp_soc *soc)
+{
+	hal_rx_dump_fse_table(soc->rx_fst->hal_rx_fst);
+}
+
+/**
+ * dp_rx_fst_attach() - Initialize Rx FST and setup necessary parameters
+ * @soc: SoC handle
+ * @pdev: Pdev handle
+ *
+ * Return: Handle to flow search table entry
+ */
+QDF_STATUS dp_rx_fst_attach(struct dp_soc *soc, struct dp_pdev *pdev)
+{
+	struct dp_rx_fst *fst;
+	uint8_t *hash_key;
+	struct wlan_cfg_dp_soc_ctxt *cfg = soc->wlan_cfg_ctx;
+
+	/* Check if it is enabled in the INI */
+	if (!wlan_cfg_is_rx_fisa_enabled(cfg)) {
+		dp_err("RX FISA feature is disabled");
+		return QDF_STATUS_E_NOSUPPORT;
+	}
+
+#ifdef NOT_YET /* Not required for now */
+	/* Check if FW supports */
+	if (!wlan_psoc_nif_fw_ext_cap_get((void *)pdev->ctrl_pdev,
+					  WLAN_SOC_CEXT_RX_FSE_SUPPORT)) {
+		QDF_TRACE(QDF_MODULE_ID_ANY, QDF_TRACE_LEVEL_ERROR,
+			  "rx fse disabled in FW\n");
+		wlan_cfg_set_rx_flow_tag_enabled(cfg, false);
+		return QDF_STATUS_E_NOSUPPORT;
+	}
+#endif
+	if (soc->rx_fst) {
+		QDF_TRACE(QDF_MODULE_ID_ANY, QDF_TRACE_LEVEL_ERROR,
+			  "RX FST already allocated\n");
+		return QDF_STATUS_SUCCESS;
+	}
+
+	fst = qdf_mem_malloc(sizeof(struct dp_rx_fst));
+	if (!fst) {
+		QDF_TRACE(QDF_MODULE_ID_ANY, QDF_TRACE_LEVEL_ERROR,
+			  "RX FST allocation failed\n");
+		return QDF_STATUS_E_NOMEM;
+	}
+
+	fst->max_skid_length = wlan_cfg_rx_fst_get_max_search(cfg);
+	fst->max_entries = wlan_cfg_get_rx_flow_search_table_size(cfg);
+	hash_key = wlan_cfg_rx_fst_get_hash_key(cfg);
+
+	fst->hash_mask = fst->max_entries - 1;
+	fst->num_entries = 0;
+	dp_err("FST setup params FT size %d, hash_mask 0x%x, skid_length %d",
+	       fst->max_entries, fst->hash_mask, fst->max_skid_length);
+
+	fst->base = (uint8_t *)qdf_mem_malloc(DP_RX_GET_SW_FT_ENTRY_SIZE *
+					       fst->max_entries);
+
+	if (!fst->base) {
+		QDF_TRACE(QDF_MODULE_ID_ANY, QDF_TRACE_LEVEL_ERROR,
+			  "Rx fst->base allocation failed, #entries:%d\n",
+			  fst->max_entries);
+
+		goto out2;
+	}
+
+	fst->hal_rx_fst = hal_rx_fst_attach(soc->osdev,
+					    &fst->hal_rx_fst_base_paddr,
+					    fst->max_entries,
+					    fst->max_skid_length, hash_key);
+
+	if (qdf_unlikely(!fst->hal_rx_fst)) {
+		QDF_TRACE(QDF_MODULE_ID_ANY, QDF_TRACE_LEVEL_ERROR,
+			  "Rx Hal fst allocation failed, #entries:%d\n",
+			  fst->max_entries);
+		goto out1;
+	}
+
+	qdf_spinlock_create(&fst->dp_rx_fst_lock);
+
+	fst->soc_hdl = soc;
+	soc->rx_fst = fst;
+	soc->fisa_enable = true;
+
+	QDF_TRACE(QDF_MODULE_ID_ANY, QDF_TRACE_LEVEL_ERROR,
+		  "Rx FST attach successful, #entries:%d\n",
+		  fst->max_entries);
+
+	return QDF_STATUS_SUCCESS;
+out1:
+	qdf_mem_free(fst->base);
+out2:
+	qdf_mem_free(fst);
+	return QDF_STATUS_E_NOMEM;
+}
+
+/**
+ * dp_rx_flow_send_fst_fw_setup() - Program FST parameters in FW/HW post-attach
+ * @soc: SoC handle
+ * @pdev: Pdev handle
+ *
+ * Return: Success when fst parameters are programmed in FW, error otherwise
+ */
+QDF_STATUS dp_rx_flow_send_fst_fw_setup(struct dp_soc *soc,
+					struct dp_pdev *pdev)
+{
+	struct dp_htt_rx_flow_fst_setup fisa_hw_fst_setup_cmd = {0};
+	struct dp_rx_fst *fst = soc->rx_fst;
+	struct wlan_cfg_dp_soc_ctxt *cfg = soc->wlan_cfg_ctx;
+	QDF_STATUS status;
+
+	/* mac_id = 0 is used to configure both macs with same FT */
+	fisa_hw_fst_setup_cmd.pdev_id = 0;
+	fisa_hw_fst_setup_cmd.max_entries = fst->max_entries;
+	fisa_hw_fst_setup_cmd.max_search = fst->max_skid_length;
+	fisa_hw_fst_setup_cmd.base_addr_lo = fst->hal_rx_fst_base_paddr &
+							0xffffffff;
+	fisa_hw_fst_setup_cmd.base_addr_hi = (fst->hal_rx_fst_base_paddr >> 32);
+	fisa_hw_fst_setup_cmd.ip_da_sa_prefix =	HTT_RX_IPV4_COMPATIBLE_IPV6;
+	fisa_hw_fst_setup_cmd.hash_key_len = HAL_FST_HASH_KEY_SIZE_BYTES;
+	fisa_hw_fst_setup_cmd.hash_key = wlan_cfg_rx_fst_get_hash_key(cfg);
+
+	status  = dp_htt_rx_flow_fst_setup(pdev, &fisa_hw_fst_setup_cmd);
+
+	return status;
+}
+
+/**
+ * dp_rx_fst_detach() - De-initialize Rx FST
+ * @soc: SoC handle
+ * @pdev: Pdev handle
+ *
+ * Return: None
+ */
+void dp_rx_fst_detach(struct dp_soc *soc, struct dp_pdev *pdev)
+{
+	struct dp_rx_fst *dp_fst;
+
+	dp_fst = soc->rx_fst;
+	if (qdf_likely(dp_fst)) {
+		hal_rx_fst_detach(dp_fst->hal_rx_fst, soc->osdev);
+		qdf_mem_free(dp_fst->base);
+		qdf_spinlock_destroy(&dp_fst->dp_rx_fst_lock);
+		qdf_mem_free(dp_fst);
+	}
+	soc->rx_fst = NULL;
+	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
+		  "Rx FST detached\n");
+}
+#else /* WLAN_SUPPORT_RX_FISA */
+
+#endif /* !WLAN_SUPPORT_RX_FISA */
+