From 2f17d8554b1cc731b143539446791e4d6bb840ba Mon Sep 17 00:00:00 2001
From: Sriram R <srirrama@codeaurora.org>
Date: Tue, 28 Jul 2020 16:17:17 +0530
Subject: [RFC 2/6] ath11k: update hw params for IPQ5018

Add new compatible string for IPQ5018 and add
required hw params for IPQ5018. The hw descriptors size and
datapath ops are similar to QCN9000, hence they are reused.

Signed-off-by: Sriram R <srirrama@codeaurora.org>
---
 drivers/net/wireless/ath/ath11k/ahb.c  |  3 +++
 drivers/net/wireless/ath/ath11k/core.c | 14 ++++++++++++++
 drivers/net/wireless/ath/ath11k/core.h |  1 +
 drivers/net/wireless/ath/ath11k/hw.h   |  5 +++++
 4 files changed, 23 insertions(+)

--- a/drivers/net/wireless/ath/ath11k/ahb.c
+++ b/drivers/net/wireless/ath/ath11k/ahb.c
@@ -24,6 +24,9 @@ static const struct of_device_id ath11k_
 	{ .compatible = "qcom,ipq6018-wifi",
 	  .data = (void *)ATH11K_HW_IPQ6018_HW10,
 	},
+	{ .compatible = "qcom,ipq5018-wifi",
+	  .data = (void *)ATH11K_HW_IPQ5018,
+	},
 	{ }
 };
 
@@ -137,12 +140,22 @@ enum ext_irq_num {
 
 static inline u32 ath11k_ahb_read32(struct ath11k_base *ab, u32 offset)
 {
-	return ioread32(ab->mem + offset);
+	if (ab->ce_remap && (offset & HAL_CE_REMAP_REG_BASE)) {
+		offset = offset - HAL_CE_REMAP_REG_BASE;
+		return ioread32(ab->mem_ce + offset);
+	} else {
+		return ioread32(ab->mem + offset);
+	}
 }
 
 static inline void ath11k_ahb_write32(struct ath11k_base *ab, u32 offset, u32 value)
 {
-	iowrite32(value, ab->mem + offset);
+	if (ab->ce_remap && (offset & HAL_CE_REMAP_REG_BASE)) {
+		offset = offset - HAL_CE_REMAP_REG_BASE;
+		iowrite32(value, ab->mem_ce + offset);
+	} else {
+		iowrite32(value, ab->mem + offset);
+	}
 }
 
 static void ath11k_ahb_kill_tasklets(struct ath11k_base *ab)
@@ -208,30 +221,52 @@ static void ath11k_ahb_clearbit32(struct
 static void ath11k_ahb_ce_irq_enable(struct ath11k_base *ab, u16 ce_id)
 {
 	const struct ce_pipe_config *ce_config;
+	u32 ie1_reg_addr, ie2_reg_addr, ie3_reg_addr;
+
+	if  (ab->hw_rev == ATH11K_HW_IPQ5018) {
+		ie1_reg_addr = CE_HOST_IPQ5018_IE_ADDRESS;
+		ie2_reg_addr = CE_HOST_IPQ5018_IE_2_ADDRESS;
+		ie3_reg_addr = CE_HOST_IPQ5018_IE_3_ADDRESS;
+	} else {
+		ie1_reg_addr = CE_HOST_IE_ADDRESS;
+		ie2_reg_addr = CE_HOST_IE_2_ADDRESS;
+		ie3_reg_addr = CE_HOST_IE_3_ADDRESS;
+	}
 
 	ce_config = &ab->hw_params.target_ce_config[ce_id];
 	if (__le32_to_cpu(ce_config->pipedir) & PIPEDIR_OUT)
-		ath11k_ahb_setbit32(ab, ce_id, CE_HOST_IE_ADDRESS);
+		ath11k_ahb_setbit32(ab, ce_id, ie1_reg_addr);
 
 	if (__le32_to_cpu(ce_config->pipedir) & PIPEDIR_IN) {
-		ath11k_ahb_setbit32(ab, ce_id, CE_HOST_IE_2_ADDRESS);
+		ath11k_ahb_setbit32(ab, ce_id, ie2_reg_addr);
 		ath11k_ahb_setbit32(ab, ce_id + CE_HOST_IE_3_SHIFT,
-				    CE_HOST_IE_3_ADDRESS);
+				    ie3_reg_addr);
 	}
 }
 
 static void ath11k_ahb_ce_irq_disable(struct ath11k_base *ab, u16 ce_id)
 {
 	const struct ce_pipe_config *ce_config;
+	u32 ie1_reg_addr, ie2_reg_addr, ie3_reg_addr;
+
+	if  (ab->hw_rev == ATH11K_HW_IPQ5018) {
+		ie1_reg_addr = CE_HOST_IPQ5018_IE_ADDRESS;
+		ie2_reg_addr = CE_HOST_IPQ5018_IE_2_ADDRESS;
+		ie3_reg_addr = CE_HOST_IPQ5018_IE_3_ADDRESS;
+	} else {
+		ie1_reg_addr = CE_HOST_IE_ADDRESS;
+		ie2_reg_addr = CE_HOST_IE_2_ADDRESS;
+		ie3_reg_addr = CE_HOST_IE_3_ADDRESS;
+	}
 
 	ce_config = &ab->hw_params.target_ce_config[ce_id];
 	if (__le32_to_cpu(ce_config->pipedir) & PIPEDIR_OUT)
-		ath11k_ahb_clearbit32(ab, ce_id, CE_HOST_IE_ADDRESS);
+		ath11k_ahb_clearbit32(ab, ce_id, ie1_reg_addr);
 
 	if (__le32_to_cpu(ce_config->pipedir) & PIPEDIR_IN) {
-		ath11k_ahb_clearbit32(ab, ce_id, CE_HOST_IE_2_ADDRESS);
+		ath11k_ahb_clearbit32(ab, ce_id, ie2_reg_addr);
 		ath11k_ahb_clearbit32(ab, ce_id + CE_HOST_IE_3_SHIFT,
-				      CE_HOST_IE_3_ADDRESS);
+				      ie3_reg_addr);
 	}
 }
 
@@ -684,6 +719,21 @@ static int ath11k_ahb_probe(struct platf
 	ab->enable_cold_boot_cal = enable_cold_boot_cal;
 	platform_set_drvdata(pdev, ab);
 
+	ab->mem_ce = ab->mem;
+	if (ab->hw_rev == ATH11K_HW_IPQ5018) {
+		/* ce register space is moved out of wcss unlike ipq8074 or ipq6018
+		 * and the space is not contiguous, hence remapping the CE registers
+		 * to a new space for accessing them.
+		 */
+		ab->mem_ce = ioremap_nocache(HAL_IPQ5018_CE_WFSS_REG_BASE, HAL_IPQ5018_CE_SIZE);
+		if (IS_ERR(ab->mem_ce)) {
+			dev_err(&pdev->dev, "ce ioremap error\n");
+			return -ENOMEM;
+		}
+		ab->ce_remap = true;
+		ab->ce_remap_base_addr = HAL_IPQ5018_CE_WFSS_REG_BASE;
+	}
+
 	ret = ath11k_core_pre_init(ab);
 	if (ret)
 		goto err_core_free;
@@ -770,6 +820,10 @@ qmi_fail:
 	ath11k_ahb_free_irq(ab);
 	ath11k_hal_srng_deinit(ab);
 	ath11k_ce_free_pipes(ab);
+
+	if (ab->ce_remap)
+		iounmap(ab->mem_ce);
+
 	ath11k_core_free(ab);
 	platform_set_drvdata(pdev, NULL);
 
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -46,6 +46,10 @@ extern unsigned int ath11k_frame_mode;
 
 #define ATH11K_MON_TIMER_INTERVAL  10
 
+/* Shift value to set the dest rings hash map to the dest control register */
+#define HAL_REO_DEST_RING_CTRL_HASH_RING_SHIFT			8
+#define HAL_IPQ5018_REO_DEST_RING_CTRL_HASH_RING_SHIFT		0
+
 enum ath11k_supported_bw {
 	ATH11K_BW_20	= 0,
 	ATH11K_BW_40	= 1,
@@ -117,6 +121,7 @@ enum ath11k_hw_rev {
 	ATH11K_HW_QCA6390_HW20,
 	ATH11K_HW_IPQ6018_HW10,
 	ATH11K_HW_QCN9074_HW10,
+	ATH11K_HW_IPQ5018,
 };
 
 enum ath11k_firmware_mode {
@@ -775,6 +780,7 @@ struct ath11k_base {
 	struct ath11k_soc_nss nss;
 
 	void __iomem *mem;
+	void __iomem *mem_ce;
 	dma_addr_t mem_pa;
 	unsigned long mem_len;
 
@@ -859,6 +865,8 @@ struct ath11k_base {
 	struct completion htc_suspend;
 
 	bool fw_recovery_support;
+	bool ce_remap;
+	u32 ce_remap_base_addr;
 
 	/* must be last */
 	u8 drv_priv[0] __aligned(sizeof(void *));
@@ -1004,6 +1012,9 @@ extern const struct service_to_pipe ath1
 
 extern const struct ce_pipe_config ath11k_target_ce_config_wlan_qcn9074[];
 extern const struct service_to_pipe ath11k_target_service_to_ce_map_wlan_qcn9074[];
+extern const struct ce_pipe_config ath11k_target_ce_config_wlan_ipq5018[];
+extern const struct service_to_pipe ath11k_target_service_to_ce_map_wlan_ipq5018[];
+
 int ath11k_core_qmi_firmware_ready(struct ath11k_base *ab);
 int ath11k_core_pre_init(struct ath11k_base *ab);
 int ath11k_core_init(struct ath11k_base *ath11k);
--- a/drivers/net/wireless/ath/ath11k/hw.h
+++ b/drivers/net/wireless/ath/ath11k/hw.h
@@ -156,6 +156,7 @@ struct ath11k_hw_params {
 	bool vdev_start_delay;
 	bool htt_peer_map_v2;
 	bool tcl_0_only;
+	u8 num_dscp_tid_map_tbl;
 	u8 spectral_fft_sz;
 	u8 spectral_fft_pad_sz;
 	u8 spectral_summary_pad_sz;
@@ -171,6 +172,7 @@ struct ath11k_hw_params {
 	bool supports_suspend;
 	u32 hal_desc_sz;
 	u32 m3_addr;
+	u8 reo_dest_ring_map_shift;
 };
 
 struct ath11k_hw_ops {
@@ -211,12 +213,15 @@ struct ath11k_hw_ops {
 	bool (*rx_desc_get_da_mcbc)(struct hal_rx_desc *desc);
 	bool (*rx_desc_mac_addr2_valid)(struct hal_rx_desc *desc);
 	u8* (*rx_desc_mpdu_start_addr2)(struct hal_rx_desc *desc);
+	void (*set_rx_fragmentation_dst_ring)(struct ath11k_base *ab);
+	u32 (*get_reo_dest_remap_config)(void);
 };
 
 extern const struct ath11k_hw_ops ipq8074_ops;
 extern const struct ath11k_hw_ops ipq6018_ops;
 extern const struct ath11k_hw_ops qca6390_ops;
 extern const struct ath11k_hw_ops qcn9074_ops;
+extern const struct ath11k_hw_ops ipq5018_ops;
 
 extern const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_ipq8074;
 extern const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_qca6390;
@@ -307,6 +312,12 @@ struct ath11k_hw_regs {
 	u32 hal_reo_tcl_ring_base_lsb;
 	u32 hal_reo_tcl_ring_hp;
 
+	u32 hal_sw2reo_ring_base_lsb;
+	u32 hal_sw2reo_ring_hp;
+
+	u32 hal_reo_cmd_ring_base_lsb;
+	u32 hal_reo_cmd_ring_hp;
+
 	u32 hal_reo_status_ring_base_lsb;
 	u32 hal_reo_status_hp;
 
@@ -330,5 +341,6 @@ struct ath11k_hw_regs {
 extern const struct ath11k_hw_regs ipq8074_regs;
 extern const struct ath11k_hw_regs qca6390_regs;
 extern const struct ath11k_hw_regs qcn9074_regs;
+extern const struct ath11k_hw_regs ipq5018_regs;
 
 #endif
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
@@ -74,6 +74,7 @@ static const struct ath11k_hw_params ath
 		.spectral_fft_pad_sz = 2,
 		.spectral_max_fft_bins = 512,
 		.spectral_fft_hdr_len = 16,
+		.num_dscp_tid_map_tbl = HAL_DSCP_TID_MAP_TBL_NUM_ENTRIES_MAX,
 
 		.interface_modes = BIT(NL80211_IFTYPE_STATION) |
 					BIT(NL80211_IFTYPE_AP) |
@@ -84,6 +85,7 @@ static const struct ath11k_hw_params ath
 		.cold_boot_calib = true,
 		.supports_suspend = false,
 		.hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074),
+		.reo_dest_ring_map_shift = HAL_REO_DEST_RING_CTRL_HASH_RING_SHIFT,
 	},
 	{
 		.hw_rev = ATH11K_HW_IPQ6018_HW10,
@@ -118,6 +120,7 @@ static const struct ath11k_hw_params ath
 		.spectral_fft_sz = 4,
 		.spectral_max_fft_bins = 512,
 		.spectral_fft_hdr_len = 16,
+		.num_dscp_tid_map_tbl = HAL_DSCP_TID_MAP_TBL_NUM_ENTRIES_MAX,
 
 		.interface_modes = BIT(NL80211_IFTYPE_STATION) |
 					BIT(NL80211_IFTYPE_AP) |
@@ -128,6 +131,7 @@ static const struct ath11k_hw_params ath
 		.cold_boot_calib = true,
 		.supports_suspend = false,
 		.hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074),
+		.reo_dest_ring_map_shift = HAL_REO_DEST_RING_CTRL_HASH_RING_SHIFT,
 	},
 	{
 		.name = "qca6390 hw2.0",
@@ -158,6 +162,7 @@ static const struct ath11k_hw_params ath
 		.htt_peer_map_v2 = false,
 		.tcl_0_only = true,
 		.spectral_fft_sz = 0,
+		.num_dscp_tid_map_tbl = HAL_DSCP_TID_MAP_TBL_NUM_ENTRIES_MAX,
 
 		.interface_modes = BIT(NL80211_IFTYPE_STATION) |
 					BIT(NL80211_IFTYPE_AP),
@@ -167,6 +172,7 @@ static const struct ath11k_hw_params ath
 		.cold_boot_calib = false,
 		.supports_suspend = true,
 		.hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074),
+		.reo_dest_ring_map_shift = HAL_REO_DEST_RING_CTRL_HASH_RING_SHIFT,
 	},
 	{
 		.name = "qcn9074 hw1.0",
@@ -196,6 +202,7 @@ static const struct ath11k_hw_params ath
 		.htt_peer_map_v2 = true,
 		.tcl_0_only = false,
 		.spectral_fft_sz = 2,
+		.num_dscp_tid_map_tbl = HAL_DSCP_TID_MAP_TBL_NUM_ENTRIES_MAX,
 
 		.interface_modes = BIT(NL80211_IFTYPE_STATION) |
 					BIT(NL80211_IFTYPE_AP) |
@@ -209,6 +216,53 @@ static const struct ath11k_hw_params ath
 		.spectral_max_fft_bins = 1024,
 		.spectral_summary_pad_sz = 16,
 		.spectral_fft_hdr_len = 24,
+		.reo_dest_ring_map_shift = HAL_REO_DEST_RING_CTRL_HASH_RING_SHIFT,
+	},
+	{
+		.hw_rev = ATH11K_HW_IPQ5018,
+		.name = "ipq5018 hw1.0",
+		.fw = {
+			.dir = "IPQ5018/hw1.0",
+			.board_size = 256 * 1024,
+			.cal_size = 256 * 1024,
+		},
+		.max_radios = 1,
+		.bdf_addr = 0x4BA00000,
+		/* hal_desc_sz is similar to qcn9074 */
+		.hal_desc_sz = sizeof(struct hal_rx_desc_qcn9074),
+		.hw_ops = &ipq5018_ops,
+		.qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ8074,
+		.ring_mask = &ath11k_hw_ring_mask_ipq8074,
+		.regs = &ipq5018_regs,
+		.m3_addr = ATH11K_QMI_IPQ5018_M3_DUMP_ADDRESS,
+		.spectral_fft_sz = 2,
+		.credit_flow = false,
+		.num_dscp_tid_map_tbl = HAL_IPQ5018_DSCP_TID_MAP_TBL_NUM_ENTRIES_MAX,
+		.interface_modes = BIT(NL80211_IFTYPE_STATION) |
+					BIT(NL80211_IFTYPE_AP) |
+					BIT(NL80211_IFTYPE_MESH_POINT),
+		.supports_monitor = true,
+		.supports_shadow_regs = false,
+		.idle_ps = false,
+		.supports_suspend = false,
+		.host_ce_config = ath11k_host_ce_config_qcn9074,
+		.ce_count = 6,
+		.target_ce_config = ath11k_target_ce_config_wlan_ipq5018,
+		.target_ce_count = 9,
+		.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_ipq5018,
+		.svc_to_ce_map_len = 17,
+		.single_pdev_only = false,
+		.needs_band_to_mac = true,
+		.rxdma1_enable = true,
+		.num_rxmda_per_pdev = 1,
+		.rx_mac_buf_ring = false,
+		.vdev_start_delay = false,
+		.htt_peer_map_v2 = true,
+		.tcl_0_only = false,
+		.spectral_max_fft_bins = 1024,
+		.spectral_summary_pad_sz = 16,
+		.spectral_fft_hdr_len = 24,
+		.reo_dest_ring_map_shift = HAL_IPQ5018_REO_DEST_RING_CTRL_HASH_RING_SHIFT,
 	},
 };
 
--- a/drivers/net/wireless/ath/ath11k/hw.c
+++ b/drivers/net/wireless/ath/ath11k/hw.c
@@ -10,6 +10,7 @@
 #include "hw.h"
 #include "core.h"
 #include "ce.h"
+#include "hif.h"
 
 /* Map from pdev index to hw mac index */
 static u8 ath11k_hw_ipq8074_mac_from_pdev_id(int pdev_idx)
@@ -324,6 +325,25 @@ struct rx_attention *ath11k_hw_ipq8074_r
 	return &desc->u.ipq8074.attention;
 }
 
+static void ath11k_hw_ipq8074_set_rx_fragmentation_dst_ring(struct ath11k_base *ab)
+{
+	u8 frag_dst_ring = HAL_SRNG_RING_ID_REO2SW1;
+	u32 reo_base = HAL_SEQ_WCSS_UMAC_REO_REG;
+	u32 val;
+
+	if (ab->nss.enabled)
+		frag_dst_ring = HAL_SRNG_REO_ALTERNATE_SELECT;
+
+	val = ath11k_hif_read32(ab, reo_base + HAL_REO1_GEN_ENABLE);
+
+	val &= ~HAL_REO1_GEN_ENABLE_FRAG_DST_RING;
+	val |= FIELD_PREP(HAL_REO1_GEN_ENABLE_FRAG_DST_RING,
+			  frag_dst_ring) |
+	       FIELD_PREP(HAL_REO1_GEN_ENABLE_AGING_LIST_ENABLE, 1) |
+	       FIELD_PREP(HAL_REO1_GEN_ENABLE_AGING_FLUSH_ENABLE, 1);
+	ath11k_hif_write32(ab, reo_base + HAL_REO1_GEN_ENABLE, val);
+}
+
 static u8 *ath11k_hw_ipq8074_rx_desc_get_msdu_payload(struct hal_rx_desc *desc)
 {
 	return &desc->u.ipq8074.msdu_payload[0];
@@ -507,6 +527,70 @@ static u8* ath11k_hw_ipq8074_rx_desc_mpd
 	return desc->u.ipq8074.mpdu_start.addr2;
 }
 
+static void ath11k_hw_ipq5018_set_rx_fragmentation_dst_ring(struct ath11k_base *ab)
+{
+	u8 frag_dst_ring = HAL_SRNG_RING_ID_REO2SW1;
+	u32 reo_base = HAL_SEQ_WCSS_UMAC_REO_REG;
+	u32 val;
+
+	if (ab->nss.enabled)
+		frag_dst_ring = HAL_SRNG_REO_ALTERNATE_SELECT;
+
+	val = ath11k_hif_read32(ab, reo_base + HAL_REO1_GEN_ENABLE);
+
+	val &= ~HAL_REO1_GEN_ENABLE_FRAG_DST_RING;
+	val |= FIELD_PREP(HAL_REO1_GEN_ENABLE_AGING_LIST_ENABLE, 1) |
+	       FIELD_PREP(HAL_REO1_GEN_ENABLE_AGING_FLUSH_ENABLE, 1);
+	ath11k_hif_write32(ab, reo_base + HAL_REO1_GEN_ENABLE, val);
+
+	val = ath11k_hif_read32(ab, reo_base + HAL_REO1_R0_MISC_CTL);
+	val &= ~HAL_REO1_MISC_CTL_FRAGMENT_DEST_RING;
+	val |= FIELD_PREP(HAL_REO1_MISC_CTL_FRAGMENT_DEST_RING,
+			  frag_dst_ring);
+	ath11k_hif_write32(ab, reo_base + HAL_REO1_R0_MISC_CTL, val);
+}
+
+static u32 ath11k_get_reo_dest_remap_config_default(void)
+{
+	u32 ring_hash_map;
+
+	/* For IPQ8074, IPQ6018, QCN9074, the first 8 bits are
+	 * are reserved/not used and the remainig 24 bits are
+	 * mapped for 8 hash values with 3 bits representing the
+	 * destination ring
+	 */
+	ring_hash_map = HAL_HASH_ROUTING_RING_SW1 << 0 |
+			HAL_HASH_ROUTING_RING_SW2 << 3 |
+			HAL_HASH_ROUTING_RING_SW3 << 6 |
+			HAL_HASH_ROUTING_RING_SW4 << 9 |
+			HAL_HASH_ROUTING_RING_SW1 << 12 |
+			HAL_HASH_ROUTING_RING_SW2 << 15 |
+			HAL_HASH_ROUTING_RING_SW3 << 18 |
+			HAL_HASH_ROUTING_RING_SW4 << 21;
+
+	return ring_hash_map;
+}
+
+static u32 ath11k_get_reo_dest_remap_config_5018(void)
+{
+	u32 ring_hash_map;
+
+	/* For IPQ5018 4 bits x 8 hash values represent the corresponding
+	 * destination rings. The 4th bit for each ring representation is
+	 * currently reserved/not used.
+	 */
+	ring_hash_map = HAL_HASH_ROUTING_RING_SW1 << 0 |
+			HAL_HASH_ROUTING_RING_SW2 << 4 |
+			HAL_HASH_ROUTING_RING_SW3 << 8 |
+			HAL_HASH_ROUTING_RING_SW4 << 12 |
+			HAL_HASH_ROUTING_RING_SW1 << 16 |
+			HAL_HASH_ROUTING_RING_SW2 << 20 |
+			HAL_HASH_ROUTING_RING_SW3 << 24 |
+			HAL_HASH_ROUTING_RING_SW4 << 28;
+
+	return ring_hash_map;
+}
+
 const struct ath11k_hw_ops ipq8074_ops = {
 	.get_hw_mac_from_pdev_id = ath11k_hw_ipq8074_mac_from_pdev_id,
 	.wmi_init_config = ath11k_init_wmi_config_ipq8074,
@@ -542,6 +626,8 @@ const struct ath11k_hw_ops ipq8074_ops =
 	.rx_desc_get_da_mcbc = ath11k_hw_ipq8074_rx_desc_get_da_mcbc,
 	.rx_desc_mac_addr2_valid = ath11k_hw_ipq8074_rx_desc_mac_addr2_valid,
 	.rx_desc_mpdu_start_addr2 = ath11k_hw_ipq8074_rx_desc_mpdu_start_addr2,
+	.set_rx_fragmentation_dst_ring = ath11k_hw_ipq8074_set_rx_fragmentation_dst_ring,
+	.get_reo_dest_remap_config = ath11k_get_reo_dest_remap_config_default,
 };
 
 const struct ath11k_hw_ops ipq6018_ops = {
@@ -579,6 +665,8 @@ const struct ath11k_hw_ops ipq6018_ops =
 	.rx_desc_get_da_mcbc = ath11k_hw_ipq8074_rx_desc_get_da_mcbc,
 	.rx_desc_mac_addr2_valid = ath11k_hw_ipq8074_rx_desc_mac_addr2_valid,
 	.rx_desc_mpdu_start_addr2 = ath11k_hw_ipq8074_rx_desc_mpdu_start_addr2,
+	.set_rx_fragmentation_dst_ring = ath11k_hw_ipq8074_set_rx_fragmentation_dst_ring,
+	.get_reo_dest_remap_config = ath11k_get_reo_dest_remap_config_default,
 };
 
 const struct ath11k_hw_ops qca6390_ops = {
@@ -613,6 +701,8 @@ const struct ath11k_hw_ops qca6390_ops =
 	.rx_desc_set_msdu_len = ath11k_hw_ipq8074_rx_desc_set_msdu_len,
 	.rx_desc_get_attention = ath11k_hw_ipq8074_rx_desc_get_attention,
 	.rx_desc_get_msdu_payload = ath11k_hw_ipq8074_rx_desc_get_msdu_payload,
+	.set_rx_fragmentation_dst_ring = ath11k_hw_ipq8074_set_rx_fragmentation_dst_ring,
+	.get_reo_dest_remap_config = ath11k_get_reo_dest_remap_config_default,
 	//TODO
 	/*	.rx_desc_get_da_mcbc,
 		.rx_desc_mac_addr2_valid,
@@ -652,8 +742,50 @@ const struct ath11k_hw_ops qcn9074_ops =
 	.rx_desc_set_msdu_len = ath11k_hw_qcn9074_rx_desc_set_msdu_len,
 	.rx_desc_get_attention = ath11k_hw_qcn9074_rx_desc_get_attention,
 	.rx_desc_get_msdu_payload = ath11k_hw_qcn9074_rx_desc_get_msdu_payload,
+	.set_rx_fragmentation_dst_ring = ath11k_hw_ipq8074_set_rx_fragmentation_dst_ring,
+	.get_reo_dest_remap_config = ath11k_get_reo_dest_remap_config_default,
 };
 
+/* IPQ5018 hw ops is similar to QCN9074 except for the dest ring remap */
+const struct ath11k_hw_ops ipq5018_ops = {
+	.get_hw_mac_from_pdev_id = ath11k_hw_ipq6018_mac_from_pdev_id,
+	.wmi_init_config = ath11k_init_wmi_config_ipq8074,
+	.mac_id_to_pdev_id = ath11k_hw_mac_id_to_pdev_id_ipq8074,
+	.mac_id_to_srng_id = ath11k_hw_mac_id_to_srng_id_ipq8074,
+	.rx_desc_get_da_mcbc = ath11k_hw_ipq8074_rx_desc_get_da_mcbc,
+	.rx_desc_mac_addr2_valid = ath11k_hw_ipq8074_rx_desc_mac_addr2_valid,
+	.rx_desc_mpdu_start_addr2 = ath11k_hw_ipq8074_rx_desc_mpdu_start_addr2,
+	.tx_mesh_enable = ath11k_hw_qcn9074_tx_mesh_enable,
+	.rx_desc_get_first_msdu = ath11k_hw_qcn9074_rx_desc_get_first_msdu,
+	.rx_desc_get_last_msdu = ath11k_hw_qcn9074_rx_desc_get_last_msdu,
+	.rx_desc_get_l3_pad_bytes = ath11k_hw_qcn9074_rx_desc_get_l3_pad_bytes,
+	.rx_desc_get_hdr_status = ath11k_hw_qcn9074_rx_desc_get_hdr_status,
+	.rx_desc_encrypt_valid = ath11k_hw_qcn9074_rx_desc_encrypt_valid,
+	.rx_desc_get_encrypt_type = ath11k_hw_qcn9074_rx_desc_get_encrypt_type,
+	.rx_desc_get_decap_type = ath11k_hw_qcn9074_rx_desc_get_decap_type,
+	.rx_desc_get_mesh_ctl = ath11k_hw_qcn9074_rx_desc_get_mesh_ctl,
+	.rx_desc_get_mpdu_seq_ctl_vld = ath11k_hw_qcn9074_rx_desc_get_mpdu_seq_ctl_vld,
+	.rx_desc_get_mpdu_fc_valid = ath11k_hw_qcn9074_rx_desc_get_mpdu_fc_valid,
+	.rx_desc_get_mpdu_start_seq_no = ath11k_hw_qcn9074_rx_desc_get_mpdu_start_seq_no,
+	.rx_desc_get_msdu_len = ath11k_hw_qcn9074_rx_desc_get_msdu_len,
+	.rx_desc_get_msdu_sgi = ath11k_hw_qcn9074_rx_desc_get_msdu_sgi,
+	.rx_desc_get_msdu_rate_mcs = ath11k_hw_qcn9074_rx_desc_get_msdu_rate_mcs,
+	.rx_desc_get_msdu_rx_bw = ath11k_hw_qcn9074_rx_desc_get_msdu_rx_bw,
+	.rx_desc_get_msdu_freq = ath11k_hw_qcn9074_rx_desc_get_msdu_freq,
+	.rx_desc_get_msdu_pkt_type = ath11k_hw_qcn9074_rx_desc_get_msdu_pkt_type,
+	.rx_desc_get_msdu_nss = ath11k_hw_qcn9074_rx_desc_get_msdu_nss,
+	.rx_desc_get_mpdu_tid = ath11k_hw_qcn9074_rx_desc_get_mpdu_tid,
+	.rx_desc_get_mpdu_peer_id = ath11k_hw_qcn9074_rx_desc_get_mpdu_peer_id,
+	.rx_desc_copy_attn_end_tlv = ath11k_hw_qcn9074_rx_desc_copy_attn_end,
+	.rx_desc_get_mpdu_start_tag = ath11k_hw_qcn9074_rx_desc_get_mpdu_start_tag,
+	.rx_desc_get_mpdu_ppdu_id = ath11k_hw_qcn9074_rx_desc_get_mpdu_ppdu_id,
+	.rx_desc_set_msdu_len = ath11k_hw_qcn9074_rx_desc_set_msdu_len,
+	.rx_desc_get_attention = ath11k_hw_qcn9074_rx_desc_get_attention,
+	.rx_desc_get_msdu_payload = ath11k_hw_qcn9074_rx_desc_get_msdu_payload,
+	.set_rx_fragmentation_dst_ring = ath11k_hw_ipq5018_set_rx_fragmentation_dst_ring,
+	.get_reo_dest_remap_config = ath11k_get_reo_dest_remap_config_5018,
+ };
+
 #define ATH11K_TX_RING_MASK_0 0x1
 #define ATH11K_TX_RING_MASK_1 0x2
 #define ATH11K_TX_RING_MASK_2 0x4
@@ -1464,6 +1596,197 @@ const struct service_to_pipe ath11k_targ
 	},
 };
 
+/* Target firmware's Copy Engine configuration for IPQ5018 */
+const struct ce_pipe_config ath11k_target_ce_config_wlan_ipq5018[] = {
+	/* CE0: host->target HTC control and raw streams */
+	{
+		.pipenum = __cpu_to_le32(0),
+		.pipedir = __cpu_to_le32(PIPEDIR_OUT),
+		.nentries = __cpu_to_le32(32),
+		.nbytes_max = __cpu_to_le32(2048),
+		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
+		.reserved = __cpu_to_le32(0),
+	},
+
+	/* CE1: target->host HTT + HTC control */
+	{
+		.pipenum = __cpu_to_le32(1),
+		.pipedir = __cpu_to_le32(PIPEDIR_IN),
+		.nentries = __cpu_to_le32(32),
+		.nbytes_max = __cpu_to_le32(2048),
+		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
+		.reserved = __cpu_to_le32(0),
+	},
+
+	/* CE2: target->host WMI */
+	{
+		.pipenum = __cpu_to_le32(2),
+		.pipedir = __cpu_to_le32(PIPEDIR_IN),
+		.nentries = __cpu_to_le32(32),
+		.nbytes_max = __cpu_to_le32(2048),
+		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
+		.reserved = __cpu_to_le32(0),
+	},
+
+	/* CE3: host->target WMI */
+	{
+		.pipenum = __cpu_to_le32(3),
+		.pipedir = __cpu_to_le32(PIPEDIR_OUT),
+		.nentries = __cpu_to_le32(32),
+		.nbytes_max = __cpu_to_le32(2048),
+		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
+		.reserved = __cpu_to_le32(0),
+	},
+
+	/* CE4: host->target HTT */
+	{
+		.pipenum = __cpu_to_le32(4),
+		.pipedir = __cpu_to_le32(PIPEDIR_OUT),
+		.nentries = __cpu_to_le32(256),
+		.nbytes_max = __cpu_to_le32(256),
+		.flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
+		.reserved = __cpu_to_le32(0),
+	},
+
+	/* CE5: target->host Pktlog */
+	{
+		.pipenum = __cpu_to_le32(5),
+		.pipedir = __cpu_to_le32(PIPEDIR_IN),
+		.nentries = __cpu_to_le32(32),
+		.nbytes_max = __cpu_to_le32(2048),
+		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
+		.reserved = __cpu_to_le32(0),
+	},
+
+	/* CE6: Reserved for target autonomous hif_memcpy */
+	{
+		.pipenum = __cpu_to_le32(6),
+		.pipedir = __cpu_to_le32(PIPEDIR_INOUT),
+		.nentries = __cpu_to_le32(32),
+		.nbytes_max = __cpu_to_le32(16384),
+		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
+		.reserved = __cpu_to_le32(0),
+	},
+
+	/* CE7 used only by Host */
+	{
+		.pipenum = __cpu_to_le32(7),
+		.pipedir = __cpu_to_le32(PIPEDIR_OUT),
+		.nentries = __cpu_to_le32(32),
+		.nbytes_max = __cpu_to_le32(2048),
+		.flags = __cpu_to_le32(0x2000),
+		.reserved = __cpu_to_le32(0),
+	},
+
+	/* CE8 target->host used only by IPA */
+	{
+		.pipenum = __cpu_to_le32(8),
+		.pipedir = __cpu_to_le32(PIPEDIR_INOUT),
+		.nentries = __cpu_to_le32(32),
+		.nbytes_max = __cpu_to_le32(16384),
+		.flags = __cpu_to_le32(CE_ATTR_FLAGS),
+		.reserved = __cpu_to_le32(0),
+	},
+};
+
+/* Map from service/endpoint to Copy Engine for IPQ5018.
+ * This table is derived from the CE TABLE, above.
+ * It is passed to the Target at startup for use by firmware.
+ */
+const struct service_to_pipe ath11k_target_service_to_ce_map_wlan_ipq5018[] = {
+	{
+		.service_id =	__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VO),
+		.pipedir =		__cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
+		.pipenum =		__cpu_to_le32(3),
+	},
+	{
+		.service_id =	__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VO),
+		.pipedir =		__cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
+		.pipenum =		__cpu_to_le32(2),
+	},
+	{
+		.service_id =	__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BK),
+		.pipedir =		__cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
+		.pipenum =		__cpu_to_le32(3),
+	},
+	{
+		.service_id =	__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BK),
+		.pipedir =		__cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
+		.pipenum =		__cpu_to_le32(2),
+	},
+	{
+		.service_id =	__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BE),
+		.pipedir =		__cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
+		.pipenum =		__cpu_to_le32(3),
+	},
+	{
+		.service_id =	__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BE),
+		.pipedir =		__cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
+		.pipenum =		__cpu_to_le32(2),
+	},
+	{
+		.service_id =	__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VI),
+		.pipedir =		__cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
+		.pipenum =		__cpu_to_le32(3),
+	},
+	{
+		.service_id =	__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VI),
+		.pipedir =		__cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
+		.pipenum =		__cpu_to_le32(2),
+	},
+	{
+		.service_id =	__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL),
+		.pipedir =		__cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
+		.pipenum =		__cpu_to_le32(3),
+	},
+	{
+		.service_id =	__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL),
+		.pipedir =		__cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
+		.pipenum =		__cpu_to_le32(2),
+	},
+
+	{
+		.service_id =	__cpu_to_le32(ATH11K_HTC_SVC_ID_RSVD_CTRL),
+		.pipedir =		__cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
+		.pipenum =		__cpu_to_le32(0),
+	},
+	{
+		.service_id =	__cpu_to_le32(ATH11K_HTC_SVC_ID_RSVD_CTRL),
+		.pipedir =		__cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
+		.pipenum =		__cpu_to_le32(1),
+	},
+
+	{
+		.service_id =	__cpu_to_le32(ATH11K_HTC_SVC_ID_TEST_RAW_STREAMS),
+		.pipedir =		__cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
+		.pipenum =		__cpu_to_le32(0),
+	},
+	{
+		.service_id =	__cpu_to_le32(ATH11K_HTC_SVC_ID_TEST_RAW_STREAMS),
+		.pipedir =		__cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
+		.pipenum =		__cpu_to_le32(1),
+	},
+	{
+		.service_id =	__cpu_to_le32(ATH11K_HTC_SVC_ID_HTT_DATA_MSG),
+		.pipedir =		__cpu_to_le32(PIPEDIR_OUT),	/* out = UL = host -> target */
+		.pipenum =		__cpu_to_le32(4),
+	},
+	{
+		.service_id =	__cpu_to_le32(ATH11K_HTC_SVC_ID_HTT_DATA_MSG),
+		.pipedir =		__cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
+		.pipenum =		__cpu_to_le32(1),
+	},
+	{
+		.service_id =	__cpu_to_le32(ATH11K_HTC_SVC_ID_PKT_LOG),
+		.pipedir =		__cpu_to_le32(PIPEDIR_IN),	/* in = DL = target -> host */
+		.pipenum =		__cpu_to_le32(5),
+	},
+
+       /* (Additions here) */
+
+	{ /* terminator entry */ }
+};
+
 const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_qcn9074 = {
 	.tx  = {
 		ATH11K_TX_RING_MASK_0,
@@ -1550,6 +1873,14 @@ const struct ath11k_hw_regs ipq8074_regs
 	.hal_reo_tcl_ring_base_lsb = 0x000003fc,
 	.hal_reo_tcl_ring_hp = 0x00003058,
 
+	/* SW2REO ring address */
+	.hal_sw2reo_ring_base_lsb = 0x000001ec,
+	.hal_sw2reo_ring_hp = 0x00003028,
+
+	/* REO CMD ring address */
+	.hal_reo_cmd_ring_base_lsb = 0x00000194,
+	.hal_reo_cmd_ring_hp = 0x00003020,
+
 	/* REO status address */
 	.hal_reo_status_ring_base_lsb = 0x00000504,
 	.hal_reo_status_hp = 0x00003070,
@@ -1621,6 +1952,14 @@ const struct ath11k_hw_regs qca6390_regs
 	.hal_reo_tcl_ring_base_lsb = 0x000003a4,
 	.hal_reo_tcl_ring_hp = 0x00003050,
 
+	/* SW2REO ring address */
+	.hal_sw2reo_ring_base_lsb = 0x000001ec,
+	.hal_sw2reo_ring_hp = 0x00003028,
+
+	/* REO CMD ring address */
+	.hal_reo_cmd_ring_base_lsb = 0x00000194,
+	.hal_reo_cmd_ring_hp = 0x00003020,
+
 	/* REO status address */
 	.hal_reo_status_ring_base_lsb = 0x000004ac,
 	.hal_reo_status_hp = 0x00003068,
@@ -1692,6 +2031,14 @@ const struct ath11k_hw_regs qcn9074_regs
 	.hal_reo_tcl_ring_base_lsb = 0x000003fc,
 	.hal_reo_tcl_ring_hp = 0x00003058,
 
+	/* SW2REO ring address */
+	.hal_sw2reo_ring_base_lsb = 0x000001ec,
+	.hal_sw2reo_ring_hp = 0x00003028,
+
+	/* REO CMD ring address */
+	.hal_reo_cmd_ring_base_lsb = 0x00000194,
+	.hal_reo_cmd_ring_hp = 0x00003020,
+
 	/* REO status address */
 	.hal_reo_status_ring_base_lsb = 0x00000504,
 	.hal_reo_status_hp = 0x00003070,
@@ -1704,6 +2051,81 @@ const struct ath11k_hw_regs qcn9074_regs
 
 	/* WBM Idle address */
 	.hal_wbm_idle_link_ring_base_lsb = 0x00000874,
+	.hal_wbm_idle_link_ring_misc = 0x00000884,
+
+	/* SW2WBM release address */
+	.hal_wbm_release_ring_base_lsb = 0x000001ec,
+
+	/* WBM2SW release address */
+	.hal_wbm0_release_ring_base_lsb = 0x00000924,
+	.hal_wbm1_release_ring_base_lsb = 0x0000097c,
+};
+
+const struct ath11k_hw_regs ipq5018_regs = {
+	/* SW2TCL(x) R0 ring configuration address */
+	.hal_tcl1_ring_base_lsb = 0x00000694,
+	.hal_tcl1_ring_base_msb = 0x00000698,
+	.hal_tcl1_ring_id =	0x0000069c,
+	.hal_tcl1_ring_misc = 0x000006a4,
+	.hal_tcl1_ring_tp_addr_lsb = 0x000006b0,
+	.hal_tcl1_ring_tp_addr_msb = 0x000006b4,
+	.hal_tcl1_ring_consumer_int_setup_ix0 = 0x000006c4,
+	.hal_tcl1_ring_consumer_int_setup_ix1 = 0x000006c8,
+	.hal_tcl1_ring_msi1_base_lsb = 0x000006dc,
+	.hal_tcl1_ring_msi1_base_msb = 0x000006e0,
+	.hal_tcl1_ring_msi1_data = 0x000006e4,
+	.hal_tcl2_ring_base_lsb = 0x000006ec,
+	.hal_tcl_ring_base_lsb = 0x0000079c,
+
+	/* TCL STATUS ring address */
+	.hal_tcl_status_ring_base_lsb = 0x000008a4,
+
+	/* REO2SW(x) R0 ring configuration address */
+	.hal_reo1_ring_base_lsb = 0x000001ec,
+	.hal_reo1_ring_base_msb = 0x000001f0,
+	.hal_reo1_ring_id = 0x000001f4,
+	.hal_reo1_ring_misc = 0x000001fc,
+	.hal_reo1_ring_hp_addr_lsb = 0x00000200,
+	.hal_reo1_ring_hp_addr_msb = 0x00000204,
+	.hal_reo1_ring_producer_int_setup = 0x00000210,
+	.hal_reo1_ring_msi1_base_lsb = 0x00000234,
+	.hal_reo1_ring_msi1_base_msb = 0x00000238,
+	.hal_reo1_ring_msi1_data = 0x0000023c,
+	.hal_reo2_ring_base_lsb = 0x00000244,
+	.hal_reo1_aging_thresh_ix_0 = 0x00000564,
+	.hal_reo1_aging_thresh_ix_1 = 0x00000568,
+	.hal_reo1_aging_thresh_ix_2 = 0x0000056c,
+	.hal_reo1_aging_thresh_ix_3 = 0x00000570,
+
+	/* REO2SW(x) R2 ring pointers (head/tail) address */
+	.hal_reo1_ring_hp = 0x00003028,
+	.hal_reo1_ring_tp = 0x0000302c,
+	.hal_reo2_ring_hp = 0x00003030,
+
+	/* REO2TCL R0 ring configuration address */
+	.hal_reo_tcl_ring_base_lsb = 0x000003fc,
+	.hal_reo_tcl_ring_hp = 0x00003058,
+
+	/* SW2REO ring address */
+	.hal_sw2reo_ring_base_lsb = 0x0000013c,
+	.hal_sw2reo_ring_hp = 0x00003018,
+
+	/* REO CMD ring address */
+	.hal_reo_cmd_ring_base_lsb = 0x000000e4,
+	.hal_reo_cmd_ring_hp = 0x00003010,
+
+	/* REO status address */
+	.hal_reo_status_ring_base_lsb = 0x00000504,
+	.hal_reo_status_hp = 0x00003070,
+
+	/* WCSS relative address */
+	.hal_seq_wcss_umac_ce0_src_reg = 0x08400000,
+	.hal_seq_wcss_umac_ce0_dst_reg = 0x08401000,
+	.hal_seq_wcss_umac_ce1_src_reg = 0x08402000,
+	.hal_seq_wcss_umac_ce1_dst_reg = 0x08403000,
+
+	/* WBM Idle address */
+	.hal_wbm_idle_link_ring_base_lsb = 0x00000874,
 	.hal_wbm_idle_link_ring_misc = 0x00000884,
 
 	/* SW2WBM release address */
--- a/drivers/net/wireless/ath/ath11k/dp.c
+++ b/drivers/net/wireless/ath/ath11k/dp.c
@@ -460,14 +460,7 @@ static int ath11k_dp_srng_common_setup(s
 	 * three bits to map to a particular ring. The ring mapping will be
 	 * 0:TCL, 1:SW1, 2:SW2, 3:SW3, 4:SW4, 5:Release, 6:FW and 7:Not used.
 	 */
-	ring_hash_map = HAL_HASH_ROUTING_RING_SW1 << 0 |
-			HAL_HASH_ROUTING_RING_SW2 << 3 |
-			HAL_HASH_ROUTING_RING_SW3 << 6 |
-			HAL_HASH_ROUTING_RING_SW4 << 9 |
-			HAL_HASH_ROUTING_RING_SW1 << 12 |
-			HAL_HASH_ROUTING_RING_SW2 << 15 |
-			HAL_HASH_ROUTING_RING_SW3 << 18 |
-			HAL_HASH_ROUTING_RING_SW4 << 21;
+	ring_hash_map = ab->hw_params.hw_ops->get_reo_dest_remap_config();
 
 	ath11k_hal_reo_hw_setup(ab, ring_hash_map);
 
@@ -1093,7 +1086,7 @@ int ath11k_dp_alloc(struct ath11k_base *
 		}
 	}
 
-	for (i = 0; i < HAL_DSCP_TID_MAP_TBL_NUM_ENTRIES_MAX; i++)
+	for (i = 0; i < ab->hw_params.num_dscp_tid_map_tbl; i++)
 		ath11k_hal_tx_set_dscp_tid_map(ab, i);
 
 	/* Init any SOC level resource for DP */
--- a/drivers/net/wireless/ath/ath11k/hal_rx.c
+++ b/drivers/net/wireless/ath/ath11k/hal_rx.c
@@ -803,22 +803,10 @@ void ath11k_hal_reo_init_cmd_ring(struct
 
 void ath11k_hal_reo_hw_setup(struct ath11k_base *ab, u32 ring_hash_map)
 {
-	u8 frag_dest_ring = HAL_SRNG_RING_ID_REO2SW1;
 	u32 reo_base = HAL_SEQ_WCSS_UMAC_REO_REG;
-	u32 val;
-
-	if (ab->nss.enabled)
-		frag_dest_ring = HAL_SRNG_REO_ALTERNATE_SELECT;
-
-	val = ath11k_hif_read32(ab, reo_base + HAL_REO1_GEN_ENABLE);
-
-	val &= ~HAL_REO1_GEN_ENABLE_FRAG_DST_RING;
-	val |= FIELD_PREP(HAL_REO1_GEN_ENABLE_FRAG_DST_RING,
-			  frag_dest_ring) |
-	       FIELD_PREP(HAL_REO1_GEN_ENABLE_AGING_LIST_ENABLE, 1) |
-	       FIELD_PREP(HAL_REO1_GEN_ENABLE_AGING_FLUSH_ENABLE, 1);
-	ath11k_hif_write32(ab, reo_base + HAL_REO1_GEN_ENABLE, val);
+	u8 reo_dest_hash_shift = ab->hw_params.reo_dest_ring_map_shift;
 
+	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);
 	ath11k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_1(ab),
@@ -832,18 +820,18 @@ 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,
-			   FIELD_PREP(HAL_REO_DEST_RING_CTRL_HASH_RING_MAP,
-				      ring_hash_map));
+			   ring_hash_map << reo_dest_hash_shift);
 	ath11k_hif_write32(ab, reo_base + HAL_REO1_DEST_RING_CTRL_IX_1,
-			   FIELD_PREP(HAL_REO_DEST_RING_CTRL_HASH_RING_MAP,
-				      ring_hash_map));
+			   ring_hash_map << reo_dest_hash_shift);
 	ath11k_hif_write32(ab, reo_base + HAL_REO1_DEST_RING_CTRL_IX_2,
-			   FIELD_PREP(HAL_REO_DEST_RING_CTRL_HASH_RING_MAP,
-				      ring_hash_map));
+			   ring_hash_map << reo_dest_hash_shift);
 	ath11k_hif_write32(ab, reo_base + HAL_REO1_DEST_RING_CTRL_IX_3,
-			   FIELD_PREP(HAL_REO_DEST_RING_CTRL_HASH_RING_MAP,
-				      ring_hash_map));
+			   ring_hash_map << reo_dest_hash_shift);
 }
 
 static inline void
--- a/drivers/net/wireless/ath/ath11k/ce.h
+++ b/drivers/net/wireless/ath/ath11k/ce.h
@@ -49,6 +49,11 @@ void ath11k_ce_byte_swap(void *mem, u32
 #define CE_HOST_IE_2_ADDRESS	0x00A18040
 #define CE_HOST_IE_3_ADDRESS	CE_HOST_IE_ADDRESS
 
+/* CE IE registers are different for IPQ5018 */
+#define CE_HOST_IPQ5018_IE_ADDRESS		0x0841804C
+#define CE_HOST_IPQ5018_IE_2_ADDRESS		0x08418050
+#define CE_HOST_IPQ5018_IE_3_ADDRESS		CE_HOST_IPQ5018_IE_ADDRESS
+
 #define CE_HOST_IE_3_SHIFT	0xC
 
 #define CE_RING_IDX_INCR(nentries_mask, idx) (((idx) + 1) & (nentries_mask))
--- a/drivers/net/wireless/ath/ath11k/hal.c
+++ b/drivers/net/wireless/ath/ath11k/hal.c
@@ -777,8 +777,16 @@ void ath11k_hal_srng_access_begin(struct
  */
 void ath11k_hal_srng_access_end(struct ath11k_base *ab, struct hal_srng *srng)
 {
+	unsigned long *mem;
+
 	lockdep_assert_held(&srng->lock);
 
+	if (srng->flags & HAL_SRNG_FLAGS_REMAP_CE_RING) {
+		mem = ab->mem_ce;
+	} else {
+		mem = ab->mem;
+	}
+
 	/* TODO: See if we need a write memory barrier here */
 	if (srng->flags & HAL_SRNG_FLAGS_LMAC_RING) {
 		/* For LMAC rings, ring pointer updates are done through FW and
@@ -798,13 +806,13 @@ void ath11k_hal_srng_access_end(struct a
 				*(volatile u32 *)srng->u.src_ring.tp_addr;
 			ath11k_hif_write32(ab,
 					   (unsigned long)srng->u.src_ring.hp_addr -
-					   (unsigned long)ab->mem,
+					   (unsigned long)mem,
 					   srng->u.src_ring.hp);
 		} else {
 			srng->u.dst_ring.last_hp = *srng->u.dst_ring.hp_addr;
 			ath11k_hif_write32(ab,
 					   (unsigned long)srng->u.dst_ring.tp_addr -
-					   (unsigned long)ab->mem,
+					   (unsigned long)mem,
 					   srng->u.dst_ring.tp);
 		}
 	}
@@ -915,6 +923,7 @@ int ath11k_hal_srng_setup(struct ath11k_
 	u32 lmac_idx;
 	int i;
 	u32 reg_base;
+	unsigned long *mem;
 
 	ring_id = ath11k_hal_srng_get_ring_id(ab, type, ring_num, mac_id);
 	if (ring_id < 0)
@@ -943,6 +952,13 @@ int ath11k_hal_srng_setup(struct ath11k_
 				      (ring_num * srng_config->reg_size[i]);
 	}
 
+	mem = ab->mem;
+
+	if (ab->ce_remap && (type == HAL_CE_DST || type == HAL_CE_SRC)) {
+		srng->flags |= HAL_SRNG_FLAGS_REMAP_CE_RING;
+		mem = ab->mem_ce;
+	}
+
 	memset(srng->ring_base_vaddr, 0,
 	       (srng->entry_size * srng->num_entries) << 2);
 
@@ -968,7 +984,7 @@ int ath11k_hal_srng_setup(struct ath11k_
 		} else {
 			if (!ab->hw_params.supports_shadow_regs)
 				srng->u.src_ring.hp_addr =
-				(u32 *)((unsigned long)ab->mem + reg_base);
+				(u32 *)((unsigned long)mem + reg_base);
 			else
 				ath11k_dbg(ab, ATH11k_DBG_HAL,
 					   "hal type %d ring_num %d reg_base 0x%x shadow 0x%lx\n",
@@ -1001,7 +1017,7 @@ int ath11k_hal_srng_setup(struct ath11k_
 		} else {
 			if (!ab->hw_params.supports_shadow_regs)
 				srng->u.dst_ring.tp_addr =
-				(u32 *)((unsigned long)ab->mem + reg_base +
+				(u32 *)((unsigned long)mem + reg_base +
 					(HAL_REO1_RING_TP(ab) - HAL_REO1_RING_HP(ab)));
 			else
 				ath11k_dbg(ab, ATH11k_DBG_HAL,
@@ -1155,12 +1171,12 @@ static int ath11k_hal_srng_create_config
 	s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_TCL_RING_HP(ab);
 
 	s = &hal->srng_config[HAL_REO_REINJECT];
-	s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_SW2REO_RING_BASE_LSB;
-	s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_SW2REO_RING_HP;
+	s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_SW2REO_RING_BASE_LSB(ab);
+	s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_SW2REO_RING_HP(ab);
 
 	s = &hal->srng_config[HAL_REO_CMD];
-	s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_CMD_RING_BASE_LSB;
-	s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_CMD_HP;
+	s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_CMD_RING_BASE_LSB(ab);
+	s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_CMD_HP(ab);
 
 	s = &hal->srng_config[HAL_REO_STATUS];
 	s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_STATUS_RING_BASE_LSB(ab);
--- a/drivers/net/wireless/ath/ath11k/hal.h
+++ b/drivers/net/wireless/ath/ath11k/hal.h
@@ -11,6 +11,8 @@
 
 struct ath11k_base;
 
+#define HAL_CE_REMAP_REG_BASE (ab->ce_remap_base_addr)
+
 #define HAL_LINK_DESC_SIZE			(32 << 2)
 #define HAL_LINK_DESC_ALIGN			128
 #define HAL_NUM_MPDUS_PER_LINK_DESC		6
@@ -27,6 +29,7 @@ struct ath11k_base;
 #define HAL_WBM_IDLE_SCATTER_BUF_SIZE (HAL_WBM_IDLE_SCATTER_BUF_SIZE_MAX - \
 				       HAL_WBM_IDLE_SCATTER_NEXT_PTR_SIZE)
 
+#define HAL_IPQ5018_DSCP_TID_MAP_TBL_NUM_ENTRIES_MAX	32
 #define HAL_DSCP_TID_MAP_TBL_NUM_ENTRIES_MAX	48
 #define HAL_DSCP_TID_TBL_SIZE			24
 
@@ -120,6 +123,7 @@ struct ath11k_base;
 #define HAL_REO1_DEST_RING_CTRL_IX_1		0x00000008
 #define HAL_REO1_DEST_RING_CTRL_IX_2		0x0000000c
 #define HAL_REO1_DEST_RING_CTRL_IX_3		0x00000010
+#define HAL_REO1_R0_MISC_CTL			0x000005d8
 #define HAL_REO1_RING_BASE_LSB(ab)		ab->hw_params.regs->hal_reo1_ring_base_lsb
 #define HAL_REO1_RING_BASE_MSB(ab)		ab->hw_params.regs->hal_reo1_ring_base_msb
 #define HAL_REO1_RING_ID(ab)			ab->hw_params.regs->hal_reo1_ring_id
@@ -179,16 +183,16 @@ struct ath11k_base;
 #define HAL_REO_TCL_RING_HP(ab)			ab->hw_params.regs->hal_reo_tcl_ring_hp
 
 /* REO CMD R0 address */
-#define HAL_REO_CMD_RING_BASE_LSB		0x00000194
+#define HAL_REO_CMD_RING_BASE_LSB(ab)		ab->hw_params.regs->hal_reo_cmd_ring_base_lsb
 
 /* REO CMD R2 address */
-#define HAL_REO_CMD_HP				0x00003020
+#define HAL_REO_CMD_HP(ab)				ab->hw_params.regs->hal_reo_cmd_ring_hp
 
 /* SW2REO R0 address */
-#define HAL_SW2REO_RING_BASE_LSB		0x000001ec
+#define HAL_SW2REO_RING_BASE_LSB(ab)		ab->hw_params.regs->hal_sw2reo_ring_base_lsb
 
 /* SW2REO R2 address */
-#define HAL_SW2REO_RING_HP			0x00003028
+#define HAL_SW2REO_RING_HP(ab)			ab->hw_params.regs->hal_sw2reo_ring_hp
 
 /* CE ring R0 address */
 #define HAL_CE_DST_RING_BASE_LSB		0x00000000
@@ -280,6 +284,7 @@ struct ath11k_base;
 #define HAL_REO1_GEN_ENABLE_FRAG_DST_RING		GENMASK(25, 23)
 #define HAL_REO1_GEN_ENABLE_AGING_LIST_ENABLE		BIT(2)
 #define HAL_REO1_GEN_ENABLE_AGING_FLUSH_ENABLE		BIT(3)
+#define HAL_REO1_MISC_CTL_FRAGMENT_DEST_RING		GENMASK(19, 17)
 
 /* CE ring bit field mask and shift */
 #define HAL_CE_DST_R0_DEST_CTRL_MAX_LEN			GENMASK(15, 0)
@@ -316,6 +321,10 @@ struct ath11k_base;
 #define HAL_WBM2SW_RELEASE_RING_BASE_MSB_RING_SIZE	0x000fffff
 #define HAL_RXDMA_RING_MAX_SIZE				0x0000ffff
 
+/* IPQ5018 ce registers */
+#define HAL_IPQ5018_CE_WFSS_REG_BASE		0x08400000
+#define HAL_IPQ5018_CE_SIZE			0x200000
+
 /* Add any other errors here and return them in
  * ath11k_hal_rx_desc_get_err().
  */
@@ -514,6 +523,7 @@ enum hal_srng_dir {
 #define HAL_SRNG_FLAGS_LOW_THRESH_INTR_EN	0x00010000
 #define HAL_SRNG_FLAGS_MSI_INTR			0x00020000
 #define HAL_SRNG_FLAGS_LMAC_RING		0x80000000
+#define HAL_SRNG_FLAGS_REMAP_CE_RING		0x10000000
 
 #define HAL_SRNG_TLV_HDR_TAG		GENMASK(9, 1)
 #define HAL_SRNG_TLV_HDR_LEN		GENMASK(25, 10)
--- a/drivers/net/wireless/ath/ath11k/qmi.h
+++ b/drivers/net/wireless/ath/ath11k/qmi.h
@@ -34,6 +34,7 @@
 #define ATH11K_QMI_DEFAULT_QDSS_CONFIG_FILE_NAME "qdss_trace_config.bin"
 #define ATH11K_QMI_IPQ8074_M3_DUMP_ADDRESS	0x51000000
 #define ATH11K_QMI_IPQ6018_M3_DUMP_ADDRESS	0x50100000
+#define ATH11K_QMI_IPQ5018_M3_DUMP_ADDRESS 0x4C800000
 #define ATH11K_QMI_M3_DUMP_SIZE			0x100000
 
 #define QMI_WLFW_REQUEST_MEM_IND_V01		0x0035
