[qca-nss-clients] Make qdisc module take a reference on IGS module.

The code change causes nss qdisc module to take a reference on the IGS
module when a qdisc is configured on an IFB interface. This ensure the
IGS module will not go away when shapers are configured on it.

Change-Id: Ib7748af0b0f41fb52afc77badc988626c4b8ec5a
Signed-off-by: Manish Verma <maniverm@codeaurora.org>
diff --git a/nss_qdisc/igs/nss_ifb.c b/nss_qdisc/igs/nss_ifb.c
index 746524c..e53781e 100644
--- a/nss_qdisc/igs/nss_ifb.c
+++ b/nss_qdisc/igs/nss_ifb.c
@@ -318,7 +318,7 @@
 
 	spin_lock_bh(&nss_ifb_list_lock);
 	if (!(ifb_info->is_mapped)) {
-		nss_igs_info("%s IFB device mapped flag is not set\n", ifb_info->map_dev->name);
+		nss_igs_info("%s IFB device mapped flag is not set\n", ifb_info->ifb_dev->name);
 		spin_unlock_bh(&nss_ifb_list_lock);
 		return true;
 	}
@@ -418,7 +418,7 @@
 
 	spin_lock_bh(&nss_ifb_list_lock);
 	if (!(ifb_info->is_mapped)) {
-		nss_igs_info("%s IFB device mapped flag is not set\n", ifb_info->map_dev->name);
+		nss_igs_info("%s IFB device mapped flag is not set\n", ifb_info->ifb_dev->name);
 		spin_unlock_bh(&nss_ifb_list_lock);
 		return true;
 	}
diff --git a/nss_qdisc/igs/nss_mirred.c b/nss_qdisc/igs/nss_mirred.c
index 5fca4e0..5ca5914 100644
--- a/nss_qdisc/igs/nss_mirred.c
+++ b/nss_qdisc/igs/nss_mirred.c
@@ -539,6 +539,11 @@
 		return err;
 	}
 
+	/*
+	 * Set the IGS module reference variable.
+	 */
+	nss_igs_module_save(&nss_mirred_act_ops, THIS_MODULE);
+
 	nss_ifb_init();
 	return 0;
 }
@@ -549,6 +554,11 @@
  */
 static void __exit nss_mirred_cleanup_module(void)
 {
+	/*
+	 * Reset the IGS module reference variable.
+	 */
+	nss_igs_module_save(&nss_mirred_act_ops, NULL);
+
 	nf_unregister_hooks(nss_mirred_igs_nf_ops, ARRAY_SIZE(nss_mirred_igs_nf_ops));
 
 	/*
diff --git a/nss_qdisc/nss_qdisc.c b/nss_qdisc/nss_qdisc.c
index b5fb2e3..83a5886 100644
--- a/nss_qdisc/nss_qdisc.c
+++ b/nss_qdisc/nss_qdisc.c
@@ -14,6 +14,7 @@
  **************************************************************************
  */
 
+#include <nss_api_if.h>
 #include "nss_qdisc.h"
 #include "nss_fifo.h"
 #include "nss_codel.h"
@@ -1880,7 +1881,9 @@
 	 * How we begin to tidy up depends on whether we are root or child
 	 */
 	nq->pending_final_state = NSS_QDISC_STATE_IDLE;
-	if (nq->is_root) {
+	if (!nq->is_root) {
+		nss_qdisc_child_cleanup_free_node(nq);
+	} else {
 
 		/*
 		 * If this is root on a bridge interface, then unassign
@@ -1897,8 +1900,12 @@
 		 */
 		nss_qdisc_root_cleanup_free_node(nq);
 
-	} else {
-		nss_qdisc_child_cleanup_free_node(nq);
+		/*
+		 * In case of IGS interface, release the reference of the IGS module.
+		 */
+		if (nss_igs_verify_if_num(nq->nss_interface_number)) {
+			nss_igs_module_put();
+		}
 	}
 
 	/*
@@ -1951,6 +1958,7 @@
 #if defined(NSS_QDISC_PPE_SUPPORT)
 	bool mode_ppe = false;
 #endif
+	bool igs_put = false;
 
 	if (accel_mode >= TCA_NSS_ACCEL_MODE_MAX) {
 		nss_qdisc_warning("Qdisc %p (type %d) accel_mode:%u should be < %u\n",
@@ -2238,15 +2246,15 @@
 		 * register for bridge bouncing as it will be responsible for
 		 * bouncing packets to the NSS for bridge shaping.
 		 */
-		if (nss_igs_verify_if_num(nq->nss_interface_number)) {
+		if (!nss_igs_verify_if_num(nq->nss_interface_number)) {
+			nq->bounce_context = nss_shaper_register_shaper_bounce_bridge(nq->nss_interface_number,
+					nss_qdisc_bounce_callback, nq->qdisc, THIS_MODULE);
+		} else {
 			nss_qdisc_error("Since %d is an IFB device, it cannot"
 					" register for bridge bouncing\n", nq->nss_interface_number);
 			nss_shaper_unregister_shaping(nq->nss_shaping_ctx);
 			atomic_set(&nq->state, NSS_QDISC_STATE_INIT_FAILED);
 			goto init_fail;
-		} else {
-			nq->bounce_context = nss_shaper_register_shaper_bounce_bridge(nq->nss_interface_number,
-					nss_qdisc_bounce_callback, nq->qdisc, THIS_MODULE);
 		}
 
 		if (!nq->bounce_context) {
@@ -2290,12 +2298,31 @@
 			/*
 			 * Register for interface bounce shaping.
 			 */
-			if (nss_igs_verify_if_num(nq->nss_interface_number)) {
-				nq->bounce_context = nss_shaper_register_shaper_bounce_interface(nq->nss_interface_number,
-						nss_qdisc_mark_and_schedule, nq->qdisc, THIS_MODULE);
-			} else {
+			if (!nss_igs_verify_if_num(nq->nss_interface_number)) {
 				nq->bounce_context = nss_shaper_register_shaper_bounce_interface(nq->nss_interface_number,
 						nss_qdisc_bounce_callback, nq->qdisc, THIS_MODULE);
+			} else {
+
+				/*
+				 * In case of IGS interface, take the reference of IGS module.
+				 */
+				if (!nss_igs_module_get()) {
+					nss_qdisc_error("Module reference failed for IGS interface %d"
+							" , Qdisc %p (type %d)\n", nq->nss_interface_number,
+							nq->qdisc, nq->type);
+					nss_shaper_unregister_shaping(nq->nss_shaping_ctx);
+					atomic_set(&nq->state, NSS_QDISC_STATE_INIT_FAILED);
+					goto init_fail;
+				}
+
+				/*
+				 * Set the flag to indicate the IGS module reference get is successful.
+				 * This flag will be used to decrement the IGS module reference in case
+				 * of any error conditions.
+				 */
+				igs_put = true;
+				nq->bounce_context = nss_shaper_register_shaper_bounce_interface(nq->nss_interface_number,
+						nss_qdisc_mark_and_schedule, nq->qdisc, THIS_MODULE);
 			}
 
 			if (!nq->bounce_context) {
@@ -2342,6 +2369,12 @@
 	 */
 	if (!wait_event_timeout(nq->wait_queue, atomic_read(&nq->state) != NSS_QDISC_STATE_IDLE,
 				NSS_QDISC_COMMAND_TIMEOUT)) {
+		/*
+		 * Decrement the IGS module reference.
+		 */
+		if (igs_put) {
+			nss_igs_module_put();
+		}
 		nss_qdisc_error("init for qdisc %x timedout!\n", nq->qos_tag);
 		return -1;
 	}
@@ -2380,6 +2413,13 @@
 
 init_fail:
 
+	/*
+	 * Decrement the IGS module reference.
+	 */
+	if (igs_put) {
+		nss_igs_module_put();
+	}
+
 #if defined(NSS_QDISC_PPE_SUPPORT)
 	if (nq->mode == NSS_QDISC_MODE_PPE) {
 		nss_ppe_destroy(nq);