Merge "[qca-nss-drv] Enable UTCM_SHARED for meminfo"
diff --git a/nss_hal/fsm9010/nss_hal_pvt.c b/nss_hal/fsm9010/nss_hal_pvt.c
index 164e5bd..360835b 100644
--- a/nss_hal/fsm9010/nss_hal_pvt.c
+++ b/nss_hal/fsm9010/nss_hal_pvt.c
@@ -310,6 +310,17 @@
 }
 
 /*
+ * __nss_hal_init_utcm_shared
+ */
+bool __nss_hal_init_utcm_shared(struct nss_ctx_instance *nss_ctx, uint32_t *meminfo_start)
+{
+	/*
+	 * Nothing to be done as there are no UTCM_SHARED defined for fsm9010
+	 */
+	return true;
+}
+
+/*
  * nss_hal_fsm9010_ops
  */
 struct nss_hal_ops nss_hal_fsm9010_ops = {
@@ -326,4 +337,5 @@
 	.clear_interrupt_cause = __nss_hal_clear_interrupt_cause,
 	.read_interrupt_cause = __nss_hal_read_interrupt_cause,
 	.init_imem = __nss_hal_init_imem,
+	.init_utcm_shared = __nss_hal_init_utcm_shared,
 };
diff --git a/nss_hal/include/nss_hal_ops.h b/nss_hal/include/nss_hal_ops.h
index 2f64923..736d37e 100644
--- a/nss_hal/include/nss_hal_ops.h
+++ b/nss_hal/include/nss_hal_ops.h
@@ -1,6 +1,6 @@
 /*
  **************************************************************************
- * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2019, 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.
@@ -44,5 +44,6 @@
 	void (*enable_interrupt)(struct nss_ctx_instance *nss_ctx, uint32_t shift_factor, uint32_t cause);
 	void (*disable_interrupt)(struct nss_ctx_instance *nss_ctx, uint32_t shift_factor, uint32_t cause);
 	void (*init_imem)(struct nss_ctx_instance *nss_ctx);
+	bool (*init_utcm_shared)(struct nss_ctx_instance *nss_ctx, uint32_t *meminfo_start);
 };
 #endif /* __NSS_HAL_OPS_H */
diff --git a/nss_hal/ipq60xx/nss_hal_pvt.c b/nss_hal/ipq60xx/nss_hal_pvt.c
index 42ce7a5..a015232 100644
--- a/nss_hal/ipq60xx/nss_hal_pvt.c
+++ b/nss_hal/ipq60xx/nss_hal_pvt.c
@@ -644,6 +644,33 @@
 }
 
 /*
+ * __nss_hal_init_utcm_shared
+ */
+bool __nss_hal_init_utcm_shared(struct nss_ctx_instance *nss_ctx, uint32_t *meminfo_start)
+{
+	struct nss_meminfo_ctx *mem_ctx = &nss_ctx->meminfo_ctx;
+	uint32_t utcm_shared_map_magic = meminfo_start[2];
+	uint32_t utcm_shared_start = meminfo_start[3];
+	uint32_t utcm_shared_size = meminfo_start[4];
+
+	/*
+	 * Check meminfo utcm_shared map magic
+	 */
+	if ((uint16_t)utcm_shared_map_magic != NSS_MEMINFO_RESERVE_AREA_UTCM_SHARED_MAP_MAGIC) {
+		nss_info_always("%p: failed to verify UTCM_SHARED map magic\n", nss_ctx);
+		return false;
+	}
+
+	mem_ctx->utcm_shared_head = utcm_shared_start;
+	mem_ctx->utcm_shared_end = mem_ctx->utcm_shared_head + utcm_shared_size;
+	mem_ctx->utcm_shared_tail = mem_ctx->utcm_shared_head;
+
+	nss_info("%p: UTCM_SHARED init: head: 0x%x end: 0x%x tail: 0x%x\n", nss_ctx,
+			mem_ctx->utcm_shared_head, mem_ctx->utcm_shared_end, mem_ctx->utcm_shared_tail);
+	return true;
+}
+
+/*
  * nss_hal_ipq60xx_ops
  */
 struct nss_hal_ops nss_hal_ipq60xx_ops = {
@@ -660,4 +687,5 @@
 	.clear_interrupt_cause = __nss_hal_clear_interrupt_cause,
 	.read_interrupt_cause = __nss_hal_read_interrupt_cause,
 	.init_imem = __nss_hal_init_imem,
+	.init_utcm_shared = __nss_hal_init_utcm_shared,
 };
diff --git a/nss_hal/ipq806x/nss_hal_pvt.c b/nss_hal/ipq806x/nss_hal_pvt.c
index e2a8203..875fc47 100644
--- a/nss_hal/ipq806x/nss_hal_pvt.c
+++ b/nss_hal/ipq806x/nss_hal_pvt.c
@@ -1203,6 +1203,17 @@
 }
 
 /*
+ * __nss_hal_init_utcm_shared
+ */
+bool __nss_hal_init_utcm_shared(struct nss_ctx_instance *nss_ctx, uint32_t *meminfo_start)
+{
+	/*
+	 * Nothing to be done as there are no UTCM_SHARED defined for ipq806x
+	 */
+	return true;
+}
+
+/*
  * nss_hal_ipq806x_ops
  */
 struct nss_hal_ops nss_hal_ipq806x_ops = {
@@ -1221,4 +1232,5 @@
 	.clear_interrupt_cause = __nss_hal_clear_interrupt_cause,
 	.read_interrupt_cause = __nss_hal_read_interrupt_cause,
 	.init_imem = __nss_hal_init_imem,
+	.init_utcm_shared = __nss_hal_init_utcm_shared,
 };
diff --git a/nss_hal/ipq807x/nss_hal_pvt.c b/nss_hal/ipq807x/nss_hal_pvt.c
index 19702a2..3b09e07 100644
--- a/nss_hal/ipq807x/nss_hal_pvt.c
+++ b/nss_hal/ipq807x/nss_hal_pvt.c
@@ -731,6 +731,17 @@
 }
 
 /*
+ * __nss_hal_init_utcm_shared
+ */
+bool __nss_hal_init_utcm_shared(struct nss_ctx_instance *nss_ctx, uint32_t *meminfo_start)
+{
+	/*
+	 * Nothing to be done as there are no TCM in ipq807x
+	 */
+	return true;
+}
+
+/*
  * nss_hal_ipq807x_ops
  */
 struct nss_hal_ops nss_hal_ipq807x_ops = {
@@ -747,4 +758,5 @@
 	.clear_interrupt_cause = __nss_hal_clear_interrupt_cause,
 	.read_interrupt_cause = __nss_hal_read_interrupt_cause,
 	.init_imem = __nss_hal_init_imem,
+	.init_utcm_shared = __nss_hal_init_utcm_shared,
 };
diff --git a/nss_meminfo.c b/nss_meminfo.c
index 8eae189..29bc594 100644
--- a/nss_meminfo.c
+++ b/nss_meminfo.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2019, 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
@@ -38,7 +38,7 @@
 /*
  * Name table of memory type presented to user.
  */
-char *nss_meminfo_memtype_table[NSS_MEMINFO_MEMTYPE_MAX] = {"IMEM", "SDRAM"};
+char *nss_meminfo_memtype_table[NSS_MEMINFO_MEMTYPE_MAX] = {"IMEM", "SDRAM", "UTCM_SHARED"};
 
 /*
  * nss_meminfo_alloc_sdram()
@@ -120,6 +120,53 @@
 }
 
 /*
+ * nss_meminfo_alloc_utcm_shared()
+ *	Allocate an UTCM_SHARED block in a sequential way.
+ */
+static uint32_t nss_meminfo_alloc_utcm_shared(struct nss_ctx_instance *nss_ctx, uint32_t size, int alignment)
+{
+	struct nss_meminfo_ctx *mem_ctx = &nss_ctx->meminfo_ctx;
+	uint32_t new_tail;
+	uint32_t addr = 0;
+	int mask;
+
+	mask = alignment - 1;
+
+	/*
+	 * Alignment has to be a power of 2.
+	 */
+	nss_assert(!(alignment & mask));
+
+	new_tail = mem_ctx->utcm_shared_tail;
+
+	/*
+	 * Align up the address if it not aligned.
+	 */
+	if (new_tail & mask)
+		new_tail = (new_tail + mask) & ~mask;
+
+	if (size > (mem_ctx->utcm_shared_end - new_tail)) {
+		nss_info_always("%p: failed to alloc an UTCM_SHARED block of size %u\n", nss_ctx, size);
+		return addr;
+	}
+
+	addr = new_tail;
+	mem_ctx->utcm_shared_tail = new_tail + size;
+
+	return addr;
+}
+
+/*
+ * nss_meminfo_free_utcm_shared()
+ *	Free an UTCM_SHARED block. Ignore the padding bytes for alignment requirement.
+ */
+static void nss_meminfo_free_utcm_shared(struct nss_ctx_instance *nss_ctx, uint32_t addr, uint32_t size)
+{
+	struct nss_meminfo_ctx *mem_ctx = &nss_ctx->meminfo_ctx;
+	mem_ctx->utcm_shared_tail -= size;
+}
+
+/*
  * nss_meminfo_if_user_overwrite()
  *	Return user configured memory type. Otherwise, return -1.
  */
@@ -181,7 +228,7 @@
 		while (b) {
 			struct nss_meminfo_block *tmp;
 			/*
-			 * Free IMEM/SDRAM memory.
+			 * Free IMEM/SDRAM/UTCM_SHARED memory.
 			 */
 			switch (i) {
 			case NSS_MEMINFO_MEMTYPE_IMEM:
@@ -190,6 +237,9 @@
 			case NSS_MEMINFO_MEMTYPE_SDRAM:
 				nss_meminfo_free_sdram(nss_ctx, b->dma_addr, b->kern_addr, b->size);
 				break;
+			case NSS_MEMINFO_MEMTYPE_UTCM_SHARED:
+				nss_meminfo_free_utcm_shared(nss_ctx, b->dma_addr, b->size);
+				break;
 			}
 
 			/*
@@ -280,6 +330,22 @@
 				goto cleanup;
 			}
 			break;
+		case NSS_MEMINFO_MEMTYPE_UTCM_SHARED:
+			/*
+			 * Return SoC real address for UTCM_SHARED as DMA address.
+			 */
+			dma_addr = nss_meminfo_alloc_utcm_shared(nss_ctx, r->size, r->alignment);
+			if (!dma_addr) {
+				nss_info_always("%p: failed to alloc UTCM_SHARED block\n", nss_ctx);
+				goto cleanup;
+			}
+			/*
+			 * There is no corresponding mapped address in kernel.
+			 * UTCM_SHARED access from kernel is not allowed. Mem Objects requesting
+			 * UTCM_SHARED are not expected to use any kernel mapped address.
+			 */
+			kern_addr = NSS_MEMINFO_POISON;
+			break;
 		default:
 			nss_info_always("%p: %d unsupported memory type\n", nss_ctx, mtype);
 			goto cleanup;
@@ -294,12 +360,14 @@
 		 * nss_if_mem_map settings
 		 */
 		if (!strcmp(r->name, "nss_if_mem_map_inst")) {
+			BUG_ON(mtype == NSS_MEMINFO_MEMTYPE_UTCM_SHARED);
 			mem_ctx->if_map_memtype = mtype;
 			mem_ctx->if_map_dma = dma_addr;
 			mem_ctx->if_map = (struct nss_if_mem_map *)kern_addr;
 		}
 
 		if (!strcmp(r->name, "debug_boot_log_desc")) {
+			BUG_ON(mtype == NSS_MEMINFO_MEMTYPE_UTCM_SHARED);
 			mem_ctx->logbuffer_memtype = mtype;
 			mem_ctx->logbuffer_dma = dma_addr;
 			mem_ctx->logbuffer = (struct nss_log_descriptor *)kern_addr;
@@ -538,6 +606,7 @@
 	seq_printf(seq, "Overwrite the /etc/modules.d/32-qca-nss-drv with following contents then reboot\n\n");
 	seq_printf(seq, "qca-nss-drv meminfo_user_config=\"<core_id, name, memory_type>, ..\"\n\n");
 	seq_printf(seq, "For example, <1, h2n_rings, IMEM> stands for: h2n_rings of core 1 is on IMEM\n");
+	seq_printf(seq, "Note:UTCM_SHARED cannot be used for n2h_rings, h2n_rings and debug_log_boot_desc.\n");
 
 	return 0;
 }
@@ -660,6 +729,14 @@
 	nss_top->hal_ops->init_imem(nss_ctx);
 
 	/*
+	 * Init UTCM_SHARED if supported
+	 */
+	if (!nss_top->hal_ops->init_utcm_shared(nss_ctx, meminfo_start)) {
+		nss_info_always("%p: failed to initialize UTCM_SHARED meminfo\n", nss_ctx);
+		return false;
+	}
+
+	/*
 	 * Init meminfo block lists
 	 */
 	if (!nss_meminfo_init_block_lists(nss_ctx)) {
diff --git a/nss_meminfo.h b/nss_meminfo.h
index c9bb3b9..0b7f822 100644
--- a/nss_meminfo.h
+++ b/nss_meminfo.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2019, 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
@@ -29,9 +29,11 @@
 #define NSS_MEMINFO_MAP_START_MAGIC	0x9527
 #define NSS_MEMINFO_REQUEST_MAGIC	0X9528
 #define NSS_MEMINFO_MAP_END_MAGIC	0x9529
+#define NSS_MEMINFO_RESERVE_AREA_UTCM_SHARED_MAP_MAGIC 	0x9530 /* Magic at the beginning of UTCM_SHARED reserved space */
 #define NSS_MEMINFO_BLOCK_NAME_MAXLEN	48
 #define NSS_MEMINFO_MEMTYPE_NAME_MAXLEN	32
 #define NSS_MEMINFO_USER_CONFIG_MAXLEN	1024
+#define NSS_MEMINFO_POISON 		0x95	/* Invalid kernel memory address assigned for non mapable mem types */
 
 /*
  * Memory types available
@@ -39,6 +41,7 @@
 enum nss_meminfo_memtype {
 	NSS_MEMINFO_MEMTYPE_IMEM,	/* NSS-IMEM also called TCM */
 	NSS_MEMINFO_MEMTYPE_SDRAM,	/* SDRAM also called DDR */
+	NSS_MEMINFO_MEMTYPE_UTCM_SHARED,	/* UTCM memory allocated for DMA objects */
 	NSS_MEMINFO_MEMTYPE_MAX
 };
 
@@ -109,6 +112,9 @@
 	uint32_t imem_head;				/* IMEM start address */
 	uint32_t imem_end;				/* IMEM end address */
 	uint32_t imem_tail;				/* IMEM data end */
+	uint32_t utcm_shared_head;				/* UTCM_SHARED start address */
+	uint32_t utcm_shared_end;				/* UTCM_SHARED end address */
+	uint32_t utcm_shared_tail;				/* UTCM_SHARED data end */
 	struct nss_if_mem_map *if_map;			/* nss_if_mem_map_inst virtual address */
 	uint32_t if_map_dma;				/* nss_if_mem_map_inst physical address */
 	enum nss_meminfo_memtype if_map_memtype;	/* Memory type for nss_if_mem_map */