[qca-nss-drv] Add support for 4 N2H DATA QUEUE

Creates 4 interrupt instances to serve NSS RPS to 4
different queues.

Change-Id: Ifb1c577c8cfa7d9a8652e0207b501da80460fc7c
Signed-off-by: Stephen Wang <wstephen@codeaurora.org>
diff --git a/nss_core.c b/nss_core.c
index fdad77b..12fef11 100644
--- a/nss_core.c
+++ b/nss_core.c
@@ -321,7 +321,7 @@
  */
 static inline uint16_t nss_core_cause_to_queue(uint16_t cause)
 {
-	if (likely(cause == NSS_N2H_INTR_DATA_COMMAND_QUEUE)) {
+	if (likely(cause == NSS_N2H_INTR_DATA_QUEUE_0)) {
 		return NSS_IF_DATA_QUEUE_0;
 	}
 
@@ -329,6 +329,14 @@
 		return NSS_IF_DATA_QUEUE_1;
 	}
 
+	if (likely(cause == NSS_N2H_INTR_DATA_QUEUE_2)) {
+		return NSS_IF_DATA_QUEUE_2;
+	}
+
+	if (likely(cause == NSS_N2H_INTR_DATA_QUEUE_3)) {
+		return NSS_IF_DATA_QUEUE_3;
+	}
+
 	if (likely(cause == NSS_N2H_INTR_EMPTY_BUFFER_QUEUE)) {
 		return NSS_IF_EMPTY_BUFFER_QUEUE;
 	}
@@ -1473,10 +1481,10 @@
 		return NSS_N2H_INTR_TX_UNBLOCKED;
 	}
 
-	if (cause & NSS_N2H_INTR_DATA_COMMAND_QUEUE) {
+	if (cause & NSS_N2H_INTR_DATA_QUEUE_0) {
 		*type = NSS_INTR_CAUSE_QUEUE;
 		*weight = NSS_DATA_COMMAND_BUFFER_PROCESSING_WEIGHT;
-		return NSS_N2H_INTR_DATA_COMMAND_QUEUE;
+		return NSS_N2H_INTR_DATA_QUEUE_0;
 	}
 
 	if (cause & NSS_N2H_INTR_DATA_QUEUE_1) {
@@ -1485,6 +1493,18 @@
 		return NSS_N2H_INTR_DATA_QUEUE_1;
 	}
 
+	if (cause & NSS_N2H_INTR_DATA_QUEUE_2) {
+		*type = NSS_INTR_CAUSE_QUEUE;
+		*weight = NSS_DATA_COMMAND_BUFFER_PROCESSING_WEIGHT;
+		return NSS_N2H_INTR_DATA_QUEUE_2;
+	}
+
+	if (cause & NSS_N2H_INTR_DATA_QUEUE_3) {
+		*type = NSS_INTR_CAUSE_QUEUE;
+		*weight = NSS_DATA_COMMAND_BUFFER_PROCESSING_WEIGHT;
+		return NSS_N2H_INTR_DATA_QUEUE_3;
+	}
+
 	if (cause & NSS_N2H_INTR_COREDUMP_COMPLETE_0) {
 		printk("NSS core 0 signal COREDUMP COMPLETE %x ", cause);
 		*type = NSS_INTR_CAUSE_EMERGENCY;
diff --git a/nss_core.h b/nss_core.h
index c7faa01..b5b1bb1 100644
--- a/nss_core.h
+++ b/nss_core.h
@@ -123,6 +123,8 @@
 #define NSS_IF_EMPTY_BUFFER_QUEUE 0
 #define NSS_IF_DATA_QUEUE_0 1
 #define NSS_IF_DATA_QUEUE_1 2
+#define NSS_IF_DATA_QUEUE_2 3
+#define NSS_IF_DATA_QUEUE_3 4
 #define NSS_IF_CMD_QUEUE 1
 
 /*
@@ -154,12 +156,13 @@
 /*
  * NSS maximum data queue per core
  */
-#define NSS_MAX_DATA_QUEUE 2
+#define NSS_MAX_DATA_QUEUE 4
 
 /*
- * NSS maximum IRQ per interrupt instance
+ * NSS maximum IRQ per interrupt instance/core
  */
-#define NSS_MAX_IRQ_PER_INSTANCE 5
+#define NSS_MAX_IRQ_PER_INSTANCE 4
+#define NSS_MAX_IRQ_PER_CORE 7
 
 /*
  * NSS maximum clients
@@ -822,6 +825,8 @@
 					/* HLOS IRQ numbers bind to this instance */
 	uint32_t shift_factor;		/* Shift factor for this IRQ queue */
 	uint32_t cause;			/* Interrupt cause carried forward to BH */
+	uint32_t queue_cause;		/* Queue cause bind to this interrupt ctx */
+	char irq_name[11];		/* IRQ name bind to this interrupt ctx */
 	struct net_device *ndev;	/* Netdev associated with this interrupt ctx */
 	struct napi_struct napi;	/* NAPI handler */
 };
@@ -1233,17 +1238,17 @@
  *      Platform data per core
  */
 struct nss_platform_data {
-	uint32_t id;					/* NSS core ID */
-	uint32_t num_queue;				/* No. of queues supported per core */
-	uint32_t num_irq;				/* No. of irq binded per queue */
-	uint32_t irq[5];				/* IRQ numbers per queue */
-	void __iomem *nmap;				/* Virtual addr of NSS CSM space */
-	void __iomem *vmap;				/* Virtual addr of NSS virtual register map */
+	uint32_t id;				/* NSS core ID */
+	uint32_t num_queue;			/* No. of queues supported per core */
+	uint32_t num_irq;			/* No. of irq binded per queue */
+	uint32_t irq[NSS_MAX_IRQ_PER_CORE];	/* IRQ numbers per queue */
+	void __iomem *nmap;			/* Virtual addr of NSS CSM space */
+	void __iomem *vmap;			/* Virtual addr of NSS virtual register map */
 	void __iomem *qgic_map;			/* Virtual addr of QGIC interrupt register */
-	uint32_t nphys;					/* Physical addr of NSS CSM space */
-	uint32_t vphys;					/* Physical addr of NSS virtual register map */
-	uint32_t qgic_phys;				/* Physical addr of QGIC virtual register map */
-	uint32_t load_addr;				/* Load address of NSS firmware */
+	uint32_t nphys;				/* Physical addr of NSS CSM space */
+	uint32_t vphys;				/* Physical addr of NSS virtual register map */
+	uint32_t qgic_phys;			/* Physical addr of QGIC virtual register map */
+	uint32_t load_addr;			/* Load address of NSS firmware */
 
 	enum nss_feature_enabled capwap_enabled;
 				/* Does this core handle capwap? */
diff --git a/nss_hal/include/nss_hal.h b/nss_hal/include/nss_hal.h
index 004dbba..1ac6e20 100644
--- a/nss_hal/include/nss_hal.h
+++ b/nss_hal/include/nss_hal.h
@@ -1,6 +1,6 @@
 /*
  **************************************************************************
- * Copyright (c) 2013, 2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013, 2016-2017 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.
@@ -43,13 +43,12 @@
 #endif
 
 #define NSS_HAL_SUPPORTED_INTERRUPTS (NSS_N2H_INTR_EMPTY_BUFFER_QUEUE | \
-					NSS_N2H_INTR_DATA_COMMAND_QUEUE | \
+					NSS_N2H_INTR_DATA_QUEUE_0 | \
 					NSS_N2H_INTR_DATA_QUEUE_1 | \
 					NSS_N2H_INTR_EMPTY_BUFFERS_SOS | \
 					NSS_N2H_INTR_TX_UNBLOCKED | \
 					NSS_N2H_INTR_COREDUMP_COMPLETE_0 | \
 					NSS_N2H_INTR_COREDUMP_COMPLETE_1)
-#define NSS_MAX_IRQ_PER_QUEUE 5
 
 /*
  * nss_hal_read_interrupt_cause()
diff --git a/nss_hal/include/nss_regs.h b/nss_hal/include/nss_regs.h
index b33b0b8..9af9508 100644
--- a/nss_hal/include/nss_regs.h
+++ b/nss_hal/include/nss_regs.h
@@ -60,8 +60,10 @@
  * both NSS cores may generate interrupt simultaneously
  */
 #define NSS_N2H_INTR_EMPTY_BUFFER_QUEUE		(1 << 0)
-#define NSS_N2H_INTR_DATA_COMMAND_QUEUE		(1 << 1)
+#define NSS_N2H_INTR_DATA_QUEUE_0		(1 << 1)
 #define NSS_N2H_INTR_DATA_QUEUE_1		(1 << 2)
+#define NSS_N2H_INTR_DATA_QUEUE_2		(1 << 3)
+#define NSS_N2H_INTR_DATA_QUEUE_3		(1 << 4)
 #define NSS_N2H_INTR_EMPTY_BUFFERS_SOS		(1 << 10)
 #define NSS_N2H_INTR_TX_UNBLOCKED		(1 << 11)
 #define NSS_N2H_INTR_COREDUMP_COMPLETE_1	(1 << 13)
diff --git a/nss_hal/ipq807x/nss_hal_pvt.c b/nss_hal/ipq807x/nss_hal_pvt.c
index f082ee6..b03534c 100644
--- a/nss_hal/ipq807x/nss_hal_pvt.c
+++ b/nss_hal/ipq807x/nss_hal_pvt.c
@@ -54,11 +54,11 @@
 /*
  * nss_hal_handle_data_cmd_irq()
  */
-static irqreturn_t nss_hal_handle_data_cmd_irq(int irq, void *ctx)
+static irqreturn_t nss_hal_handle_data_cmd_queue_irq(int irq, void *ctx)
 {
 	struct int_ctx_instance *int_ctx = (struct int_ctx_instance *) ctx;
 
-	int_ctx->cause |= NSS_N2H_INTR_DATA_COMMAND_QUEUE;
+	int_ctx->cause |= int_ctx->queue_cause;
 
 	if (napi_schedule_prep(&int_ctx->napi))
 		__napi_schedule(&int_ctx->napi);
@@ -97,21 +97,6 @@
 }
 
 /*
- * nss_hal_handle_data_queue_one_irq()
- */
-static irqreturn_t nss_hal_handle_data_queue_one_irq(int irq, void *ctx)
-{
-	struct int_ctx_instance *int_ctx = (struct int_ctx_instance *) ctx;
-
-	int_ctx->cause |= NSS_N2H_INTR_DATA_QUEUE_1;
-
-	if (napi_schedule_prep(&int_ctx->napi))
-		__napi_schedule(&int_ctx->napi);
-
-	return IRQ_HANDLED;
-}
-
-/*
  * nss_hal_handle_tx_unblock_irq()
  */
 static irqreturn_t nss_hal_handle_tx_unblock_irq(int irq, void *ctx)
@@ -429,15 +414,19 @@
 	int err;
 
 	/*
-	 * Queue1 use the last (#5) IRQ and queue0 use #1 to #4
+	 * Queue0-3 use the IRQ #4 to #7, and are mapped to cause bit 1 to 4
 	 */
-	if (qnum == 1) {
-		err = request_irq(npd->irq[4], nss_hal_handle_data_queue_one_irq, 0, "nss_queue1", int_ctx);
-		if (err) {
-			nss_info_always("%p: IRQ%d request failed", int_ctx, npd->irq[4]);
-			return err;
-		}
-		int_ctx->irq[0] = npd->irq[4];
+	snprintf(int_ctx->irq_name, 11, "nss_queue%d", qnum);
+	int_ctx->queue_cause = (1 << (qnum+1));
+	err = request_irq(npd->irq[qnum+3], nss_hal_handle_data_cmd_queue_irq, 0, int_ctx->irq_name, int_ctx);
+	if (err) {
+		nss_info_always("%p: IRQ%d request failed", int_ctx, npd->irq[qnum+3]);
+		return err;
+	}
+
+	int_ctx->irq[0] = npd->irq[qnum+3];
+
+	if (qnum) {
 		return 0;
 	}
 
@@ -446,28 +435,24 @@
 		nss_info_always("%p: IRQ%d request failed", int_ctx, npd->irq[0]);
 		return err;
 	}
-	int_ctx->irq[0] = npd->irq[0];
 
-	err = request_irq(npd->irq[1], nss_hal_handle_data_cmd_irq, 0, "nss_queue0", int_ctx);
+	int_ctx->irq[1] = npd->irq[0];
+
+	err = request_irq(npd->irq[1], nss_hal_handle_empty_buff_queue_irq, 0, "nss_empty_buf_queue", int_ctx);
 	if (err) {
 		nss_info_always("%p: IRQ%d request failed", int_ctx, npd->irq[1]);
 		return err;
 	}
-	int_ctx->irq[1] = npd->irq[1];
 
-	err = request_irq(npd->irq[2], nss_hal_handle_empty_buff_queue_irq, 0, "nss_empty_buf_queue", int_ctx);
+	int_ctx->irq[2] = npd->irq[1];
+
+	err = request_irq(npd->irq[2], nss_hal_handle_tx_unblock_irq, 0, "nss-tx-unblock", int_ctx);
 	if (err) {
 		nss_info_always("%p: IRQ%d request failed", int_ctx, npd->irq[2]);
 		return err;
 	}
-	int_ctx->irq[2] = npd->irq[2];
 
-	err = request_irq(npd->irq[3], nss_hal_handle_tx_unblock_irq, 0, "nss-tx-unblock", int_ctx);
-	if (err) {
-		nss_info_always("%p: IRQ%d request failed", int_ctx, npd->irq[3]);
-		return err;
-	}
-	int_ctx->irq[3] = npd->irq[3];
+	int_ctx->irq[3] = npd->irq[2];
 
 	return 0;
 }
diff --git a/nss_hal/nss_hal.c b/nss_hal/nss_hal.c
index 537bde1..7970602 100644
--- a/nss_hal/nss_hal.c
+++ b/nss_hal/nss_hal.c
@@ -142,12 +142,17 @@
 {
 	int i;
 
-	for (i = 0; i < NSS_MAX_IRQ_PER_QUEUE; i++) {
+	for (i = 0; i < NSS_MAX_IRQ_PER_INSTANCE; i++) {
 		if (int_ctx->irq[i]) {
 			free_irq(int_ctx->irq[i], int_ctx);
 			int_ctx->irq[i] = 0;
 		}
 	}
+
+	if (!int_ctx->ndev) {
+		return;
+	}
+
 	unregister_netdev(int_ctx->ndev);
 	free_netdev(int_ctx->ndev);
 	int_ctx->ndev = NULL;
@@ -196,7 +201,6 @@
 	err = nss_top->hal_ops->request_irq_for_queue(nss_ctx, npd, qnum);
 	if (err) {
 		nss_warning("%p: IRQ request for queue %d failed", nss_ctx, qnum);
-		nss_hal_clean_up_netdevice(int_ctx);
 		return err;
 	}
 
@@ -312,26 +316,10 @@
 	nss_info("%d:ctx=%p, vphys=%x, vmap=%p, nphys=%x, nmap=%p", nss_ctx->id,
 			nss_ctx, nss_ctx->vphys, nss_ctx->vmap, nss_ctx->nphys, nss_ctx->nmap);
 
-	/*
-	 * Register netdevice for queue 0
-	 */
-	err = nss_hal_register_netdevice(nss_ctx, npd, 0);
-	if (err) {
-		goto err_init;
-	}
-
-	/*
-	 * Check if second interrupt is supported on this nss core
-	 */
-	if (npd->num_queue > 1) {
-		nss_info("%d: This NSS core supports two interrupts", nss_dev->id);
-
-		/*
-		 * Register netdevice for queue 1
-		 */
-		err = nss_hal_register_netdevice(nss_ctx, npd, 1);
+	for (i = 0; i < npd->num_queue; i++) {
+		err = nss_hal_register_netdevice(nss_ctx, npd, i);
 		if (err) {
-			goto err_register_netdev_0;
+			goto err_register_netdevice;
 		}
 	}
 
@@ -523,7 +511,7 @@
 	 */
 	err = nss_top->hal_ops->core_reset(nss_dev, nss_ctx->nmap, nss_ctx->load, nss_top->clk_src);
 	if (err) {
-		goto err_register_netdev_1;
+		goto err_register_netdevice;
 	}
 
 	/*
@@ -562,11 +550,10 @@
 	nss_info("%p: All resources initialized and nss core%d has been brought out of reset", nss_ctx, nss_dev->id);
 	goto out;
 
-err_register_netdev_1:
-	nss_hal_clean_up_netdevice(&nss_ctx->int_ctx[1]);
-
-err_register_netdev_0:
-	nss_hal_clean_up_netdevice(&nss_ctx->int_ctx[0]);
+err_register_netdevice:
+	for (i = 0; i < npd->num_queue; i++) {
+		nss_hal_clean_up_netdevice(&nss_ctx->int_ctx[i]);
+	}
 
 err_init:
 	if (nss_dev->dev.of_node) {