From 60d0a63d537c280ff9501296cefd322b981b88f5 Mon Sep 17 00:00:00 2001
From: P Praneesh <ppranees@codeaurora.org>
Date: Mon, 14 Dec 2020 19:13:49 +0530
Subject: [PATCH] ath11k: Add provision to configure rx hashmap

Currently the hashmap is set to default during REO
setup and all REO rings are equally distributed across
32 hash values.

Add provision to configure the hashmap so that destination
rings can be controlled. Setting 0 will disable hash based
steering.

echo "hashmap" > /sys/kernel/debug/ath11k/ipq8074\ hw2.0/rx_hash

Signed-off-by: Sriram R <srirrama@codeaurora.org>
Signed-off-by: P Praneesh <ppranees@codeaurora.org>
---
 drivers/net/wireless/ath/ath11k/core.h   |  2 ++
 drivers/net/wireless/ath/ath11k/debugfs.c  | 51 ++++++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath11k/dp.c     |  4 ++-
 drivers/net/wireless/ath/ath11k/hal.h    |  1 +
 drivers/net/wireless/ath/ath11k/hal_rx.c | 30 +++++++++++--------
 5 files changed, 74 insertions(+), 14 deletions(-)

--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -967,6 +967,8 @@ struct ath11k_base {
 	struct ath11k_internal_pci ipci;
 	bool enable_memory_stats;
 
+	u32 rx_hash;
+
 	/* must be last */
 	u8 drv_priv[0] __aligned(sizeof(void *));
 };
--- a/drivers/net/wireless/ath/ath11k/debugfs.c
+++ b/drivers/net/wireless/ath/ath11k/debugfs.c
@@ -1414,6 +1414,55 @@ static const struct file_operations fops
 	.llseek = default_llseek,
 };
 
+static ssize_t ath11k_write_rx_hash(struct file *file,
+				    const char __user *ubuf,
+				    size_t count, loff_t *ppos)
+{
+	struct ath11k_base *ab = file->private_data;
+	struct ath11k_pdev *pdev;
+	u32 rx_hash;
+	u8 buf[128] = {0};
+	int ret, i, radioup = 0;
+
+	for (i = 0; i < ab->num_radios; i++) {
+		pdev = &ab->pdevs[i];
+		if (pdev && pdev->ar) {
+			radioup = 1;
+			break;
+		}
+	}
+
+	if (radioup == 0) {
+		ath11k_err(ab, "radio is not up\n");
+		ret = -ENETDOWN;
+		goto exit;
+	}
+
+	ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count);
+	if (ret < 0)
+		goto exit;
+
+	buf[ret] = '\0';
+	ret = sscanf(buf, "%x", &rx_hash);
+	if (!ret) {
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	if (rx_hash != ab->rx_hash) {
+		ab->rx_hash = rx_hash;
+		if (rx_hash)
+			ath11k_hal_reo_hash_setup(ab, rx_hash);
+	}
+	ret = count;
+exit:
+	return ret;
+}
+static const struct file_operations fops_soc_rx_hash = {
+	.open = simple_open,
+	.write = ath11k_write_rx_hash,
+};
+
 static ssize_t ath11k_debug_write_fw_recovery(struct file *file,
                                               char __user *user_buf,
                                               size_t count, loff_t *ppos)
@@ -1688,6 +1737,9 @@ int ath11k_debugfs_pdev_create(struct at
 	debugfs_create_file("ce_latency_stats", 0600, ab->debugfs_soc, ab,
 			    &fops_ce_latency_stats);
 
+	debugfs_create_file("rx_hash", 0600, ab->debugfs_soc, ab,
+			    &fops_soc_rx_hash);
+
 	return 0;
 }
 
@@ -1840,7 +1892,6 @@ static ssize_t ath11k_write_pktlog_filte
 	debugfs_create_file("memory_stats", 0600, ab->debugfs_soc, ab,
 			    &fops_memory_stats);
 
-
 #define HTT_RX_FILTER_TLV_LITE_MODE \
 			(HTT_RX_FILTER_TLV_FLAGS_PPDU_START | \
 			HTT_RX_FILTER_TLV_FLAGS_PPDU_END | \
--- a/drivers/net/wireless/ath/ath11k/dp.c
+++ b/drivers/net/wireless/ath/ath11k/dp.c
@@ -48,7 +48,7 @@ int ath11k_dp_peer_setup(struct ath11k *
 	bool rx_hash_enable = DP_RX_HASH_ENABLE;
 
 	/* RX Hash based steering is disabled for NSS Offload */
-	if (ar->ab->nss.enabled)
+	if (ar->ab->nss.enabled || !ab->rx_hash)
 		rx_hash_enable = DP_RX_HASH_DISABLE;
 
 	/* NOTE: reo_dest ring id starts from 1 unlike mac_id which starts from 0 */
@@ -468,6 +468,8 @@ static int ath11k_dp_srng_common_setup(s
 
 	ath11k_hal_reo_hw_setup(ab, ring_hash_map);
 
+	ab->rx_hash = ring_hash_map;
+
 	return 0;
 
 err:
--- a/drivers/net/wireless/ath/ath11k/hal.h
+++ b/drivers/net/wireless/ath/ath11k/hal.h
@@ -917,6 +917,7 @@ void ath11k_hal_reo_qdesc_setup(void *va
 void ath11k_hal_reo_init_cmd_ring(struct ath11k_base *ab,
 				  struct hal_srng *srng);
 void ath11k_hal_reo_hw_setup(struct ath11k_base *ab, u32 ring_hash_map);
+void ath11k_hal_reo_hash_setup(struct ath11k_base *ab, u32 ring_hash_map);
 void ath11k_hal_setup_link_idle_list(struct ath11k_base *ab,
 				     struct hal_wbm_idle_scatter_list *sbuf,
 				     u32 nsbufs, u32 tot_link_desc,
--- a/drivers/net/wireless/ath/ath11k/hal_rx.c
+++ b/drivers/net/wireless/ath/ath11k/hal_rx.c
@@ -801,11 +801,25 @@ void ath11k_hal_reo_init_cmd_ring(struct
 	}
 }
 
-void ath11k_hal_reo_hw_setup(struct ath11k_base *ab, u32 ring_hash_map)
+void ath11k_hal_reo_hash_setup(struct ath11k_base *ab, u32 ring_hash_map)
 {
 	u32 reo_base = HAL_SEQ_WCSS_UMAC_REO_REG;
 	u8 reo_dest_hash_shift = ab->hw_params.reo_dest_ring_map_shift;
 
+	/* These registers use only 24bits(3 bits x 8 hash values) for
+	 * mapping the dest rings and remaining bits are reserved/not used
+	 * so its safe to write them completely.
+	 */
+	ath11k_hif_write32(ab, reo_base + HAL_REO1_DEST_RING_CTRL_IX_2,
+			   ring_hash_map << reo_dest_hash_shift);
+	ath11k_hif_write32(ab, reo_base + HAL_REO1_DEST_RING_CTRL_IX_3,
+			   ring_hash_map << reo_dest_hash_shift);
+}
+
+void ath11k_hal_reo_hw_setup(struct ath11k_base *ab, u32 ring_hash_map)
+{
+	u32 reo_base = HAL_SEQ_WCSS_UMAC_REO_REG;
+
 	ab->hw_params.hw_ops->set_rx_fragmentation_dst_ring(ab);
 	ath11k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_0(ab),
 			   HAL_DEFAULT_REO_TIMEOUT_USEC);
@@ -820,18 +834,7 @@ void ath11k_hal_reo_hw_setup(struct ath1
 	if (ab->nss.enabled)
 		return;
 
-	/* These registers use only 24bits(3 bits x 8 hash values) for
-	 * mapping the dest rings and remaining bits are reserved/not used
-	 * so its safe to write them completely.
-	 */
-	ath11k_hif_write32(ab, reo_base + HAL_REO1_DEST_RING_CTRL_IX_0,
-			   ring_hash_map << reo_dest_hash_shift);
-	ath11k_hif_write32(ab, reo_base + HAL_REO1_DEST_RING_CTRL_IX_1,
-			   ring_hash_map << reo_dest_hash_shift);
-	ath11k_hif_write32(ab, reo_base + HAL_REO1_DEST_RING_CTRL_IX_2,
-			   ring_hash_map << reo_dest_hash_shift);
-	ath11k_hif_write32(ab, reo_base + HAL_REO1_DEST_RING_CTRL_IX_3,
-			   ring_hash_map << reo_dest_hash_shift);
+	ath11k_hal_reo_hash_setup(ab, ring_hash_map);
 }
 
 static inline void
