qcacld-3.0: add support to customize dscp-to-up map table

Add support to customize DSCP-to-UP map table and send the
customized map values to FW to update its corresponding
map table.

Change-Id: Ibe9704a90468c898dd2e60fdf83a271152f654ce
CRs-Fixed: 2616247
diff --git a/Kbuild b/Kbuild
index d128727..f09fa79 100644
--- a/Kbuild
+++ b/Kbuild
@@ -3140,6 +3140,9 @@
 
 cppflags-$(CONFIG_WDI3_STATS_UPDATE) += -DWDI3_STATS_UPDATE
 
+cppflags-$(CONFIG_WLAN_CUSTOM_DSCP_UP_MAP) += -DWLAN_CUSTOM_DSCP_UP_MAP
+cppflags-$(CONFIG_WLAN_SEND_DSCP_UP_MAP_TO_FW) += -DWLAN_SEND_DSCP_UP_MAP_TO_FW
+
 KBUILD_CPPFLAGS += $(cppflags-y)
 
 # Currently, for versions of gcc which support it, the kernel Makefile
diff --git a/components/fw_offload/dispatcher/inc/wlan_fwol_public_structs.h b/components/fw_offload/dispatcher/inc/wlan_fwol_public_structs.h
index ea0863b..10f253a 100644
--- a/components/fw_offload/dispatcher/inc/wlan_fwol_public_structs.h
+++ b/components/fw_offload/dispatcher/inc/wlan_fwol_public_structs.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2019-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
@@ -76,6 +76,7 @@
  * @get_elna_bypass: get eLNA bypass
  * @reg_evt_handler: register event handler
  * @unreg_evt_handler: unregister event handler
+ * @send_dscp_up_map_to_fw: send dscp-to-up map values to FW
  */
 struct wlan_fwol_tx_ops {
 #ifdef WLAN_FEATURE_ELNA
@@ -88,6 +89,11 @@
 				      void *arg);
 	QDF_STATUS (*unreg_evt_handler)(struct wlan_objmgr_psoc *psoc,
 					void *arg);
+#ifdef WLAN_SEND_DSCP_UP_MAP_TO_FW
+	QDF_STATUS (*send_dscp_up_map_to_fw)(
+			struct wlan_objmgr_psoc *psoc,
+			uint32_t *dscp_to_up_map);
+#endif
 };
 
 /**
diff --git a/components/fw_offload/dispatcher/inc/wlan_fwol_ucfg_api.h b/components/fw_offload/dispatcher/inc/wlan_fwol_ucfg_api.h
index 4eace38..9c9fa98 100644
--- a/components/fw_offload/dispatcher/inc/wlan_fwol_ucfg_api.h
+++ b/components/fw_offload/dispatcher/inc/wlan_fwol_ucfg_api.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-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
@@ -543,6 +543,27 @@
 				     struct get_elna_bypass_response *response),
 				     void *context);
 #endif /* WLAN_FEATURE_ELNA */
+
+#ifdef WLAN_SEND_DSCP_UP_MAP_TO_FW
+/**
+ * ucfg_fwol_send_dscp_up_map_to_fw() - send dscp_up map to FW
+ * @vdev: vdev handle
+ * @dscp_to_up_map: DSCP to UP map array
+ *
+ * Return: QDF_STATUS_SUCCESS on success
+ */
+QDF_STATUS ucfg_fwol_send_dscp_up_map_to_fw(
+		struct wlan_objmgr_vdev *vdev,
+		uint32_t *dscp_to_up_map);
+#else
+static inline
+QDF_STATUS ucfg_fwol_send_dscp_up_map_to_fw(
+		struct wlan_objmgr_vdev *vdev,
+		uint32_t *dscp_to_up_map)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
 #else
 static inline QDF_STATUS ucfg_fwol_psoc_open(struct wlan_objmgr_psoc *psoc)
 {
diff --git a/components/fw_offload/dispatcher/src/wlan_fwol_ucfg_api.c b/components/fw_offload/dispatcher/src/wlan_fwol_ucfg_api.c
index 5cabba3..e66c986 100644
--- a/components/fw_offload/dispatcher/src/wlan_fwol_ucfg_api.c
+++ b/components/fw_offload/dispatcher/src/wlan_fwol_ucfg_api.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-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
@@ -896,3 +896,34 @@
 	return status;
 }
 #endif /* WLAN_FEATURE_ELNA */
+
+#ifdef WLAN_SEND_DSCP_UP_MAP_TO_FW
+QDF_STATUS ucfg_fwol_send_dscp_up_map_to_fw(struct wlan_objmgr_vdev *vdev,
+					   uint32_t *dscp_to_up_map)
+{
+	QDF_STATUS status;
+	struct wlan_objmgr_psoc *psoc;
+	struct wlan_fwol_psoc_obj *fwol_obj;
+	struct wlan_fwol_tx_ops *tx_ops;
+
+	psoc = wlan_vdev_get_psoc(vdev);
+	if (!psoc) {
+		fwol_err("NULL pointer for psoc");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	fwol_obj = fwol_get_psoc_obj(psoc);
+	if (!fwol_obj) {
+		fwol_err("Failed to get FWOL Obj");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	tx_ops = &fwol_obj->tx_ops;
+	if (tx_ops && tx_ops->send_dscp_up_map_to_fw)
+		status = tx_ops->send_dscp_up_map_to_fw(psoc, dscp_to_up_map);
+	else
+		status = QDF_STATUS_E_IO;
+
+	return status;
+}
+#endif /* WLAN_SEND_DSCP_UP_MAP_TO_FW */
diff --git a/components/target_if/fw_offload/src/target_if_fwol.c b/components/target_if/fw_offload/src/target_if_fwol.c
index 6aa936a..11b6510 100644
--- a/components/target_if/fw_offload/src/target_if_fwol.c
+++ b/components/target_if/fw_offload/src/target_if_fwol.c
@@ -201,6 +201,45 @@
 }
 #endif /* WLAN_FEATURE_ELNA */
 
+#ifdef WLAN_SEND_DSCP_UP_MAP_TO_FW
+/**
+ * target_if_fwol_send_dscp_up_map_to_fw() - send dscp up map to FW
+ * @psoc: pointer to PSOC object
+ * @dscp_to_up_map: DSCP to UP map array
+ *
+ * Return: QDF_STATUS_SUCCESS on success
+ */
+static QDF_STATUS
+target_if_fwol_send_dscp_up_map_to_fw(struct wlan_objmgr_psoc *psoc,
+				     uint32_t *dscp_to_up_map)
+{
+	QDF_STATUS status;
+	wmi_unified_t wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
+
+	if (!wmi_handle) {
+		target_if_err("Invalid wmi_handle");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	status = wmi_unified_send_dscp_tip_map_cmd(wmi_handle, dscp_to_up_map);
+	if (status)
+		target_if_err("Failed to send dscp_up_map_to_fw %d", status);
+
+	return status;
+}
+
+static void
+target_if_fwol_register_dscp_up_tx_ops(struct wlan_fwol_tx_ops *tx_ops)
+{
+	tx_ops->send_dscp_up_map_to_fw = target_if_fwol_send_dscp_up_map_to_fw;
+}
+#else
+static void
+target_if_fwol_register_dscp_up_tx_ops(struct wlan_fwol_tx_ops *tx_ops)
+{
+}
+#endif
+
 QDF_STATUS target_if_fwol_register_event_handler(struct wlan_objmgr_psoc *psoc,
 						 void *arg)
 {
@@ -221,6 +260,7 @@
 QDF_STATUS target_if_fwol_register_tx_ops(struct wlan_fwol_tx_ops *tx_ops)
 {
 	target_if_fwol_register_elna_tx_ops(tx_ops);
+	target_if_fwol_register_dscp_up_tx_ops(tx_ops);
 
 	tx_ops->reg_evt_handler = target_if_fwol_register_event_handler;
 	tx_ops->unreg_evt_handler = target_if_fwol_unregister_event_handler;
diff --git a/configs/default_defconfig b/configs/default_defconfig
index 0f2438f..026158d 100644
--- a/configs/default_defconfig
+++ b/configs/default_defconfig
@@ -615,6 +615,12 @@
 CONFIG_PKTLOG_LEGACY := y
 endif
 
+#Customize DSCP_to-UP map based on RFC8325
+ifeq ($(CONFIG_HELIUMPLUS), y)
+CONFIG_WLAN_CUSTOM_DSCP_UP_MAP := y
+CONFIG_WLAN_SEND_DSCP_UP_MAP_TO_FW := y
+endif
+
 ifeq ($(CONFIG_ROME_IF), sdio)
 CONFIG_PKTLOG_LEGACY := y
 endif
diff --git a/core/hdd/inc/wlan_hdd_wmm.h b/core/hdd/inc/wlan_hdd_wmm.h
index a78733c..a519f1f 100644
--- a/core/hdd/inc/wlan_hdd_wmm.h
+++ b/core/hdd/inc/wlan_hdd_wmm.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2012,2016-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2012,2016-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
@@ -205,6 +205,17 @@
 int hdd_wmmps_helper(struct hdd_adapter *adapter, uint8_t *ptr);
 
 /**
+ * hdd_send_dscp_up_map_to_fw() - send dscp to up map to FW
+ * @adapter : [in]  pointer to Adapter context
+ *
+ * This function will send the WMM DSCP configuration of an
+ * adapter to FW.
+ *
+ * Return: QDF_STATUS enumeration
+ */
+QDF_STATUS hdd_send_dscp_up_map_to_fw(struct hdd_adapter *adapter);
+
+/**
  * hdd_wmm_init() - initialize the WMM DSCP configuation
  * @adapter : [in]  pointer to Adapter context
  *
diff --git a/core/hdd/src/wlan_hdd_wmm.c b/core/hdd/src/wlan_hdd_wmm.c
index dd4cfdf..759fdbd 100644
--- a/core/hdd/src/wlan_hdd_wmm.c
+++ b/core/hdd/src/wlan_hdd_wmm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-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
@@ -47,6 +47,7 @@
 #include <linux/semaphore.h>
 #include <linux/ipv6.h>
 #include "osif_sync.h"
+#include "os_if_fwol.h"
 #include <wlan_hdd_tx_rx.h>
 #include <wlan_hdd_wmm.h>
 #include <wlan_hdd_ether.h>
@@ -55,8 +56,10 @@
 #include <cds_sched.h>
 #include "sme_api.h"
 #include "wlan_mlme_ucfg_api.h"
+#include "cfg_ucfg_api.h"
 
 #define HDD_WMM_UP_TO_AC_MAP_SIZE 8
+#define DSCP(x)	x
 
 const uint8_t hdd_wmm_up_to_ac_map[] = {
 	SME_AC_BE,
@@ -1456,6 +1459,92 @@
 	osif_vdev_sync_op_stop(vdev_sync);
 }
 
+QDF_STATUS hdd_send_dscp_up_map_to_fw(struct hdd_adapter *adapter)
+{
+	uint32_t *dscp_to_up_map = adapter->dscp_to_up_map;
+	struct wlan_objmgr_vdev *vdev = adapter->vdev;
+	int ret;
+
+	if (vdev) {
+		/* Send DSCP to TID map table to FW */
+		ret = os_if_fwol_send_dscp_up_map_to_fw(vdev, dscp_to_up_map);
+		if (ret && ret != -EOPNOTSUPP)
+			return QDF_STATUS_E_FAILURE;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * hdd_fill_dscp_to_up_map() - Fill up dscp_to_up_map table with default values
+ * @dscp_to_up_map: Array of DSCP-to-UP map
+ *
+ * This function will fill up the DSCP-to-UP map table with default values.
+ *
+ * Return: QDF_STATUS enumeration
+ */
+static inline void hdd_fill_dscp_to_up_map(
+		enum sme_qos_wmmuptype *dscp_to_up_map)
+{
+	uint8_t dscp;
+
+	/*
+	 * DSCP to User Priority Lookup Table
+	 * By default use the 3 Precedence bits of DSCP as the User Priority
+	 *
+	 * In case of changing the default map values, need to take care of
+	 * hdd_custom_dscp_up_map as well.
+	 */
+	for (dscp = 0; dscp <= WLAN_MAX_DSCP; dscp++)
+		dscp_to_up_map[dscp] = dscp >> 3;
+
+	/* Special case for Expedited Forwarding (DSCP 46) in default mapping */
+	dscp_to_up_map[DSCP(46)] = SME_QOS_WMM_UP_VO;
+}
+
+#ifdef WLAN_CUSTOM_DSCP_UP_MAP
+/**
+ * hdd_custom_dscp_up_map() - Customize dscp_to_up_map based on RFC8325
+ * @dscp_to_up_map: Array of DSCP-to-UP map
+ *
+ * This function will customize the DSCP-to-UP map table based on RFC8325..
+ *
+ * Return: QDF_STATUS enumeration
+ */
+static inline QDF_STATUS hdd_custom_dscp_up_map(
+		enum sme_qos_wmmuptype *dscp_to_up_map)
+{
+	/*
+	 * Customizing few of DSCP to UP mapping based on RFC8325,
+	 * those are different from default hdd_fill_dscp_to_up_map values.
+	 * So, below changes are always relative to hdd_fill_dscp_to_up_map.
+	 */
+	dscp_to_up_map[DSCP(10)] = SME_QOS_WMM_UP_BE;
+	dscp_to_up_map[DSCP(12)] = SME_QOS_WMM_UP_BE;
+	dscp_to_up_map[DSCP(14)] = SME_QOS_WMM_UP_BE;
+	dscp_to_up_map[DSCP(16)] = SME_QOS_WMM_UP_BE;
+
+	dscp_to_up_map[DSCP(18)] = SME_QOS_WMM_UP_EE;
+	dscp_to_up_map[DSCP(20)] = SME_QOS_WMM_UP_EE;
+	dscp_to_up_map[DSCP(22)] = SME_QOS_WMM_UP_EE;
+
+	dscp_to_up_map[DSCP(24)] = SME_QOS_WMM_UP_CL;
+	dscp_to_up_map[DSCP(26)] = SME_QOS_WMM_UP_CL;
+	dscp_to_up_map[DSCP(28)] = SME_QOS_WMM_UP_CL;
+	dscp_to_up_map[DSCP(30)] = SME_QOS_WMM_UP_CL;
+
+	dscp_to_up_map[DSCP(44)] = SME_QOS_WMM_UP_VO;
+
+	return QDF_STATUS_SUCCESS;
+}
+#else
+static inline QDF_STATUS hdd_custom_dscp_up_map(
+		enum sme_qos_wmmuptype *dscp_to_up_map)
+{
+	return QDF_STATUS_E_NOSUPPORT;
+}
+#endif /* WLAN_CUSTOM_DSCP_UP_MAP */
+
 /**
  * hdd_wmm_init() - initialize the WMM DSCP configuation
  * @adapter : [in]  pointer to Adapter context
@@ -1469,20 +1558,24 @@
 QDF_STATUS hdd_wmm_init(struct hdd_adapter *adapter)
 {
 	enum sme_qos_wmmuptype *dscp_to_up_map = adapter->dscp_to_up_map;
-	uint8_t dscp;
+	struct wlan_objmgr_psoc *psoc = adapter->hdd_ctx->psoc;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
 
 	hdd_enter();
 
-	/* DSCP to User Priority Lookup Table
-	 * By default use the 3 Precedence bits of DSCP as the User Priority
-	 */
-	for (dscp = 0; dscp <= WLAN_MAX_DSCP; dscp++)
-		dscp_to_up_map[dscp] = dscp >> 3;
+	if (!psoc) {
+		hdd_err("Invalid psoc handle");
+		return QDF_STATUS_E_FAILURE;
+	}
 
-	/* Special case for Expedited Forwarding (DSCP 46) */
-	dscp_to_up_map[46] = SME_QOS_WMM_UP_VO;
+	hdd_fill_dscp_to_up_map(dscp_to_up_map);
 
-	return QDF_STATUS_SUCCESS;
+	if (hdd_custom_dscp_up_map(dscp_to_up_map) == QDF_STATUS_SUCCESS) {
+		/* Send DSCP to TID map table to FW */
+		status = hdd_send_dscp_up_map_to_fw(adapter);
+	}
+
+	return status;
 }
 
 /**
diff --git a/os_if/fw_offload/inc/os_if_fwol.h b/os_if/fw_offload/inc/os_if_fwol.h
index ec8a08f..8ecbc0f 100644
--- a/os_if/fw_offload/inc/os_if_fwol.h
+++ b/os_if/fw_offload/inc/os_if_fwol.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2019-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
@@ -64,4 +64,22 @@
 }
 #endif /* WLAN_FEATURE_ELNA */
 
+#ifdef WLAN_SEND_DSCP_UP_MAP_TO_FW
+/**
+ * os_if_fwol_send_dscp_up_map_to_fw() - Send DSCP to UP map to FW
+ * @vdev: Pointer to vdev
+ * @dscp_to_up_map: Array of DSCP to UP map values
+ *
+ * Return: 0 on success; error number otherwise
+ */
+int os_if_fwol_send_dscp_up_map_to_fw(struct wlan_objmgr_vdev *vdev,
+				     uint32_t *dscp_to_up_map);
+#else
+static inline int os_if_fwol_send_dscp_up_map_to_fw(
+		struct wlan_objmgr_vdev *vdev, uint32_t *dscp_to_up_map)
+{
+	return -EOPNOTSUPP;
+}
+#endif /* WLAN_SEND_DSCP_UP_MAP_TO_FW */
+
 #endif /* __OS_IF_FWOL_H__ */
diff --git a/os_if/fw_offload/src/os_if_fwol.c b/os_if/fw_offload/src/os_if_fwol.c
index bcb4c7d..90ee997 100644
--- a/os_if/fw_offload/src/os_if_fwol.c
+++ b/os_if/fw_offload/src/os_if_fwol.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2019-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
@@ -131,3 +131,17 @@
 	return ret;
 }
 #endif /* #ifdef WLAN_FEATURE_ELNA */
+
+#ifdef WLAN_SEND_DSCP_UP_MAP_TO_FW
+int os_if_fwol_send_dscp_up_map_to_fw(struct wlan_objmgr_vdev *vdev,
+				     uint32_t *dscp_to_up_map)
+{
+	QDF_STATUS status;
+
+	status = ucfg_fwol_send_dscp_up_map_to_fw(vdev, dscp_to_up_map);
+	if (!QDF_IS_STATUS_SUCCESS(status))
+		osif_err("Failed to send dscp_up_map to FW, %d", status);
+
+	return qdf_status_to_os_return(status);
+}
+#endif