Merge "qca-wifi: MSCS module implementation"
diff --git a/dp/wifi3.0/dp_mscs.c b/dp/wifi3.0/dp_mscs.c
new file mode 100644
index 0000000..a69beaf
--- /dev/null
+++ b/dp/wifi3.0/dp_mscs.c
@@ -0,0 +1,108 @@
+/*
+ * 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_peer.h"
+#include "qdf_nbuf.h"
+#include "dp_types.h"
+#include "dp_internal.h"
+#include "dp_tx.h"
+#include "dp_mscs.h"
+
+#define DP_MSCS_INVALID_TID 0xFF
+#define DP_MSCS_VALID_TID_MASK 0x7
+
+/**
+ * dp_mscs_peer_lookup_n_get_priority() - Get priority for MSCS peer
+ * @soc_hdl - soc handle
+ * @src_mac_addr - src mac address from connection
+ * @nbuf - network buffer
+ *
+ * Return: 0 when peer has active mscs session and valid user priority
+ */
+int dp_mscs_peer_lookup_n_get_priority(struct cdp_soc_t *soc_hdl,
+		uint8_t *src_mac_addr, qdf_nbuf_t nbuf)
+{
+	struct dp_peer *peer;
+	uint8_t user_prio_bitmap;
+	uint8_t user_prio_limit;
+	uint8_t user_prio;
+	int status = 0;
+	struct dp_soc *dpsoc = cdp_soc_t_to_dp_soc(soc_hdl);
+
+	if (!dpsoc) {
+		QDF_TRACE(QDF_MODULE_ID_MSCS, QDF_TRACE_LEVEL_ERROR,
+				"%s: Invalid soc\n", __func__);
+		return -1;
+	}
+
+	/*
+	 * Find the MSCS peer from global soc
+	 */
+	peer = dp_peer_find_hash_find(dpsoc, src_mac_addr, 0,
+			DP_VDEV_ALL, DP_MOD_ID_MSCS);
+
+	if (!peer) {
+		/*
+		 * No WLAN client peer found with this peer mac
+		 */
+		return -1;
+	}
+
+	/*
+	 * check if there is any active MSCS session for this peer
+	 */
+	if (!peer->mscs_active) {
+		QDF_TRACE(QDF_MODULE_ID_MSCS, QDF_TRACE_LEVEL_DEBUG,
+				"%s: MSCS session not active on peer or peer delete in progress\n", __func__);
+		status = 1;
+		goto fail;
+	}
+
+	/*
+	 * Get user priority bitmap for this peer MSCS active session
+	 */
+	user_prio_bitmap = peer->mscs_ipv4_parameter.user_priority_bitmap;
+	user_prio_limit = peer->mscs_ipv4_parameter.user_priority_limit;
+	user_prio = qdf_nbuf_get_priority(nbuf) & DP_MSCS_VALID_TID_MASK;
+
+	/*
+	 * check if nbuf priority is matching with any of the valid priority value
+	 */
+	if (!((1 << user_prio) & user_prio_bitmap)) {
+		QDF_TRACE(QDF_MODULE_ID_MSCS, QDF_TRACE_LEVEL_DEBUG,
+				"%s: Nbuf TID is not valid, no match in user prioroty bitmap\n", __func__);
+		status = 1;
+		goto fail;
+	}
+
+	user_prio = QDF_MIN(user_prio, user_prio_limit);
+
+	/*
+	 * Update skb priority
+	 */
+	qdf_nbuf_set_priority(nbuf, user_prio);
+	QDF_TRACE(QDF_MODULE_ID_MSCS, QDF_TRACE_LEVEL_DEBUG,
+			"%s: User priority for this MSCS session %d\n", __func__, user_prio);
+	status = 0;
+
+fail:
+	if (peer)
+		dp_peer_unref_delete(peer, DP_MOD_ID_MSCS);
+	return status;
+}
+
+qdf_export_symbol(dp_mscs_peer_lookup_n_get_priority);
diff --git a/dp/wifi3.0/dp_mscs.h b/dp/wifi3.0/dp_mscs.h
new file mode 100644
index 0000000..911fe5c
--- /dev/null
+++ b/dp/wifi3.0/dp_mscs.h
@@ -0,0 +1,28 @@
+
+/*
+ * 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.
+ */
+
+#ifndef _DP_MSCS_H_
+#define _DP_MSCS_H_
+
+#if WLAN_SUPPORT_MSCS
+int dp_mscs_peer_lookup_n_get_priority(struct cdp_soc_t *soc_hdl,
+		        uint8_t *src_mac_addr, qdf_nbuf_t nbuf);
+#endif
+
+#endif /* QCA_MSCS_H*/
diff --git a/qca_mscs/inc/qca_mscs.h b/qca_mscs/inc/qca_mscs.h
new file mode 100644
index 0000000..e8c8339
--- /dev/null
+++ b/qca_mscs/inc/qca_mscs.h
@@ -0,0 +1,32 @@
+
+/*
+ * 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.
+ */
+
+#ifndef __qca_mscs_H_
+#define __qca_mscs_H_
+#include <qdf_module.h>
+#include <qdf_nbuf.h>
+#include <qdf_trace.h>
+#include <ol_if_athvar.h>
+
+#if WLAN_SUPPORT_MSCS
+void qca_mscs_module_init(ol_ath_soc_softc_t *soc);
+void qca_mscs_module_deinit(ol_ath_soc_softc_t *soc);
+#endif
+
+#endif /* qca_mscs_H*/
diff --git a/qca_mscs/inc/qca_mscs_if.h b/qca_mscs/inc/qca_mscs_if.h
new file mode 100644
index 0000000..002f05e
--- /dev/null
+++ b/qca_mscs/inc/qca_mscs_if.h
@@ -0,0 +1,24 @@
+
+/*
+ * 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.
+ */
+
+#ifndef __qca_mscs_if_H_
+#define __qca_mscs_if_H_
+
+int qca_mscs_peer_lookup_n_get_priority(uint8_t *src_mac, struct sk_buff *skb);
+#endif /* qca_mscs_if_H*/
diff --git a/qca_mscs/src/qca_mscs.c b/qca_mscs/src/qca_mscs.c
new file mode 100644
index 0000000..2110bbb
--- /dev/null
+++ b/qca_mscs/src/qca_mscs.c
@@ -0,0 +1,124 @@
+/*
+ * 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 "qca_mscs.h"
+#include "qca_mscs_if.h"
+
+static int mscs_soc_attached_count;
+extern ol_ath_soc_softc_t *ol_global_soc[GLOBAL_SOC_SIZE];
+
+/**
+ * qca_mscs_peer_lookup_n_get_priority() - Find MSCS enabled peer and priority
+ * @src_mac - src mac address to be used for peer lookup
+ * @nbuf - network buffer
+ * @priority - priority/tid to be updated
+ *
+ * Return: QDF_STATUS_SUCCESS for successful peer lookup
+ */
+int qca_mscs_peer_lookup_n_get_priority(uint8_t *src_mac, struct sk_buff *skb)
+{
+	uint8_t i = 0;
+	ol_ath_soc_softc_t *soc = NULL;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	ol_txrx_soc_handle soc_txrx_handle = NULL;
+	qdf_nbuf_t nbuf = (qdf_nbuf_t)skb;
+
+	/*
+	 * Loop over all the attached soc for peer lookup
+	 * with given src mac address
+	 */
+	for (i = 0; i < GLOBAL_SOC_SIZE; i++) {
+		if (!ol_global_soc[i])
+			continue;
+
+		soc = ol_global_soc[i];
+		soc_txrx_handle = wlan_psoc_get_dp_handle(soc->psoc_obj);
+		status = cdp_mscs_peer_lookup_n_get_priority(soc_txrx_handle,
+				src_mac, nbuf);
+		/*
+		 * wifi peer is found with this mac address.there can
+		 * be 3 possiblities -
+		 * 1. peer has no active MSCS session.
+		 * 2. peer has active MSCS session but priority not valid.
+		 * 3. peer has active MSCS session and priority is valid.
+		 * return the status to ECM classifier.
+		 */
+		if (status >= QDF_STATUS_SUCCESS)
+			return status;
+		/*
+		 * no wifi peer exists in this soc with given src mac address
+		 * iterate over next soc
+		 */
+	}
+
+	if (i == GLOBAL_SOC_SIZE)
+		/*
+		 * No wlan peer is found in any of attached
+		 * soc with given mac address
+		 * return the status to ECM classifier.
+		 */
+		status = QDF_STATUS_E_FAILURE;
+
+	return status;
+}
+
+qdf_export_symbol(qca_mscs_peer_lookup_n_get_priority);
+
+/**
+ * qca_mscs_module_init() - Initialize the MSCS module
+ * @soc - Pointer to soc getting attached
+ *
+ * Return: void
+ */
+
+void qca_mscs_module_init(ol_ath_soc_softc_t *soc)
+{
+	/* Check if soc max init count is reached */
+	if (mscs_soc_attached_count >= GLOBAL_SOC_SIZE)
+		return;
+
+	QDF_TRACE(QDF_MODULE_ID_MSCS, QDF_TRACE_LEVEL_INFO,
+			     FL("\n****QCA MSCS Initialization Done**** SoC %pK"), soc);
+
+	mscs_soc_attached_count++;
+}
+
+qdf_export_symbol(qca_mscs_module_init);
+
+/**
+ * qca_mscs_module_deinit() - De-Initialize MSCS module
+ * @soc - Pointer to soc getting detached
+ *
+ * Return: void
+ */
+void qca_mscs_module_deinit(ol_ath_soc_softc_t *soc)
+{
+	if (!soc)
+		return;
+
+	/*
+	 * All soc are detached by now
+	 */
+	if (mscs_soc_attached_count < 0)
+		return;
+
+	QDF_TRACE(QDF_MODULE_ID_MSCS, QDF_TRACE_LEVEL_INFO,
+			FL("\n****QCA MSCS De-Initialization Done**** SoC %pK"), soc);
+	mscs_soc_attached_count--;
+}
+
+qdf_export_symbol(qca_mscs_module_deinit);