[qca-nss-drv] Callback notifier for GRE rx packet.

 Notifier call back register/unregister.

Change-Id: I9350a2a52b1c92ce374ee719485f4e35df5ef82e
Signed-off-by: ratheesh kannoth <rkannoth@codeaurora.org>
diff --git a/exports/nss_gre.h b/exports/nss_gre.h
index a6fec7c..d2a2d19 100644
--- a/exports/nss_gre.h
+++ b/exports/nss_gre.h
@@ -21,6 +21,9 @@
 #ifndef _NSS_GRE_H_
 #define _NSS_GRE_H_
 
+#include <net/ip_tunnels.h>
+#include <net/ip6_tunnel.h>
+
 /**
  * @addtogroup nss_gre_subsystem
  * @{
@@ -48,6 +51,21 @@
 #define NSS_GRE_CONFIG_NEXT_NODE_AVAILABLE  0x00000800	/**< Use provided next_node instead of existing next node. */
 
 /**
+ * nss_gre_info
+ *	GRE private information.
+ */
+struct nss_gre_info {
+	union {
+		struct ip_tunnel t4;	/**< IPv4 tunnel */
+		struct ip6_tnl t6;	/**< IPv6 tunnel */
+	} t;
+	int nss_if_number;		/**< NSS interface number */
+	struct net_device *next_dev;	/**< Next net device */
+	uint8_t gre_hlen;		/**< GRE header length */
+	uint8_t pad_len;		/**< Pad length */
+};
+
+/**
  * nss_gre_msg_types
  *	Message types for GRE requests and responses.
  */
@@ -215,8 +233,8 @@
  * nss_ctx_instance \n
  * nss_gre_msg
  *
- * @param[in]     nss_ctx  Pointer to the NSS context.
- * @param[in]     msg      Pointer to the message data.
+ * @param[in] nss_ctx  Pointer to the NSS context.
+ * @param[in] msg      Pointer to the message data.
  *
  * @return
  * Status of the Tx operation.
@@ -231,8 +249,8 @@
  * nss_ctx_instance \n
  * nss_gre_msg
  *
- * @param[in]     nss_ctx  Pointer to the NSS context.
- * @param[in]     msg      Pointer to the message data.
+ * @param[in] nss_ctx  Pointer to the NSS context.
+ * @param[in] msg      Pointer to the message data.
  *
  * @return
  * Status of the Tx operation.
@@ -247,9 +265,9 @@
  * nss_ctx_instance \n
  * sk_buff
  *
- * @param[in]     nss_ctx  Pointer to the NSS context.
- * @param[in]     if_num   Nss interface number.
- * @param[in]     skb	   Pointer to sk_buff.
+ * @param[in] nss_ctx  Pointer to the NSS context.
+ * @param[in] if_num   Nss interface number.
+ * @param[in] skb      Pointer to sk_buff.
  *
  * @return Tx status
  */
@@ -282,11 +300,10 @@
  * nss_gre_base_debug_stats_get
  *	Gets NSS GRE base debug statistics.
  *
- * @param[in] stats_mem	Pointer to memory to which stats should be copied.
- * @param[in] size 	Stats memory size.
+ * @param[in]  stats_mem  Pointer to memory to which stats should be copied.
+ * @param[in]  size 	  Stats memory size.
  * @param[out] stats_mem  Pointer to the memory address, which must be large
  *                         enough to hold all the statistics.
- *
  * @return
  * None.
  */
@@ -296,11 +313,10 @@
  * nss_gre_session_debug_stats_get
  *	Gets NSS GRE session debug statistics.
  *
- * @param[in] stats_mem	  Pointer to memory to which stats should be copied.
- * @param[in] size 	  Stats memory size.
+ * @param[in]  stats_mem  Pointer to memory to which stats should be copied.
+ * @param[in]  size 	  Stats memory size.
  * @param[out] stats_mem  Pointer to the memory address, which must be large
  *                         enough to hold all the statistics.
- *
  * @return
  * None.
  */
@@ -316,11 +332,11 @@
  * nss_gre_msg_callback_t \n
  * net_device
  *
- * @param[in] if_num			NSS interface number.
- * @param[in] nss_gre_data_callback     Callback for the data.
- * @param[in] msg_callback		Callback for the message.
- * @param[in] netdev			Pointer to the associated network device.
- * @param[in] features			Socket buffer types supported by this interface.
+ * @param[in] if_num		     NSS interface number.
+ * @param[in] nss_gre_data_callback  Callback for the data.
+ * @param[in] msg_callback	     Callback for the message.
+ * @param[in] netdev		     Pointer to the associated network device.
+ * @param[in] features		     Socket buffer types supported by this interface.
  *
  * @return
  * Pointer to the NSS core context.
@@ -371,6 +387,47 @@
 extern void nss_gre_register_handler(void);
 
 /**
+ * Callback function for updating stats.
+ *
+ * @datatypes
+ * net_device \n
+ * sk_buff \n
+ *
+ * @param[in] netdev  Pointer to the associated network device.
+ * @param[in] skb     Pointer to the data socket buffer.
+ *
+ * @return
+ * None.
+ */
+typedef void (*nss_gre_pkt_callback_t)(struct net_device *netdev, struct sk_buff *skb);
+
+/**
+ * nss_gre_register_pkt_callback
+ *	Register for rx packet call back.
+ *
+ * @datatypes
+ * nss_gre_pkt_callback_t
+ *
+ * @param[in] cb  Call back function which needs to be registered.
+ *
+ * @return
+ * None.
+ */
+extern void nss_gre_register_pkt_callback(nss_gre_pkt_callback_t cb);
+
+/**
+ * nss_gre_unregister_pkt_callback
+ *	Unregister for rx packet call back.
+ *
+ * @datatypes
+ * nss_gre_pkt_callback_t
+ *
+ * @return
+ * None.
+ */
+extern void nss_gre_unregister_pkt_callback(void);
+
+/**
  * @}
  */
 
diff --git a/nss_core.h b/nss_core.h
index 23243d4..7ab62a3 100644
--- a/nss_core.h
+++ b/nss_core.h
@@ -1127,6 +1127,8 @@
 					/* map-t interface event callback function */
 	nss_gre_msg_callback_t gre_msg_callback;
 					/* gre interface event callback function */
+	nss_gre_data_callback_t gre_data_callback;
+					/* gre data callback function */
 	nss_tunipip6_msg_callback_t tunipip6_msg_callback;
 					/* ipip6 tunnel interface event callback function */
 	nss_pptp_msg_callback_t pptp_msg_callback;
diff --git a/nss_gre.c b/nss_gre.c
index a86bbd1..78704ef 100644
--- a/nss_gre.c
+++ b/nss_gre.c
@@ -36,6 +36,29 @@
 static struct nss_stats_gre_session_debug session_debug_stats[NSS_GRE_MAX_DEBUG_SESSION_STATS];
 static struct nss_stats_gre_base_debug base_debug_stats;
 
+static atomic64_t pkt_cb_addr = ATOMIC64_INIT(0);
+
+/*
+ * nss_gre_rx_handler()
+ *	GRE rx handler.
+ */
+static void nss_gre_rx_handler(struct net_device *dev, struct sk_buff *skb,
+		    __attribute__((unused)) struct napi_struct *napi)
+{
+	nss_gre_data_callback_t cb;
+
+	nss_gre_pkt_callback_t scb = (nss_gre_pkt_callback_t)(unsigned long)atomic64_read(&pkt_cb_addr);
+	if (unlikely(scb)) {
+		struct nss_gre_info *info = (struct nss_gre_info *)netdev_priv(dev);
+		if (likely(info->next_dev)) {
+			scb(info->next_dev, skb);
+		}
+	}
+
+	cb = nss_top_main.gre_data_callback;
+	cb(dev, skb, 0);
+}
+
 /*
  * nss_gre_session_debug_stats_sync()
  *	debug statistics sync for GRE session.
@@ -56,34 +79,10 @@
 }
 
 /*
- * nss_gre_session_debug_stats_get()
- *	Get GRE session debug statistics.
- */
-void nss_gre_session_debug_stats_get(void *stats_mem, int size)
-{
-	struct nss_stats_gre_session_debug *stats = (struct nss_stats_gre_session_debug *)stats_mem;
-	int i;
-
-	if (!stats || (size < (sizeof(struct nss_stats_gre_session_debug) * NSS_STATS_GRE_SESSION_DEBUG_MAX)))  {
-		nss_warning("No memory to copy gre stats");
-		return;
-	}
-
-	spin_lock_bh(&nss_gre_stats_lock);
-	for (i = 0; i < NSS_GRE_MAX_DEBUG_SESSION_STATS; i++) {
-		if (session_debug_stats[i].valid) {
-			memcpy(stats, &session_debug_stats[i], sizeof(struct nss_stats_gre_session_debug));
-			stats++;
-		}
-	}
-	spin_unlock_bh(&nss_gre_stats_lock);
-}
-
-/*
  * nss_gre_base_debug_stats_sync()
  *	Debug statistics sync for GRE base node.
  */
-void nss_gre_base_debug_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_gre_base_stats_msg *bstats)
+static void nss_gre_base_debug_stats_sync(struct nss_ctx_instance *nss_ctx, struct nss_gre_base_stats_msg *bstats)
 {
 	int i;
 	spin_lock_bh(&nss_gre_stats_lock);
@@ -94,29 +93,6 @@
 }
 
 /*
- * nss_gre_base_debug_stats_get()
- *	Get GRE debug base statistics.
- */
-void nss_gre_base_debug_stats_get(void *stats_mem, int size)
-{
-	struct nss_stats_gre_base_debug *stats = (struct nss_stats_gre_base_debug *)stats_mem;
-
-	if (!stats) {
-		nss_warning("No memory to copy GRE base stats\n");
-		return;
-	}
-
-	if (size < sizeof(struct nss_stats_gre_base_debug)) {
-		nss_warning("Not enough memory to copy GRE base stats\n");
-		return;
-	}
-
-	spin_lock_bh(&nss_gre_stats_lock);
-	memcpy(stats, &base_debug_stats, sizeof(struct nss_stats_gre_base_debug));
-	spin_unlock_bh(&nss_gre_stats_lock);
-}
-
-/*
  * nss_gre_msg_handler()
  *	Handle NSS -> HLOS messages for GRE
  */
@@ -219,6 +195,73 @@
 }
 
 /*
+ * nss_gre_session_debug_stats_get()
+ *	Get GRE session debug statistics.
+ */
+void nss_gre_session_debug_stats_get(void *stats_mem, int size)
+{
+	struct nss_stats_gre_session_debug *stats = (struct nss_stats_gre_session_debug *)stats_mem;
+	int i;
+
+	if (!stats || (size < (sizeof(struct nss_stats_gre_session_debug) * NSS_STATS_GRE_SESSION_DEBUG_MAX)))  {
+		nss_warning("No memory to copy gre stats");
+		return;
+	}
+
+	spin_lock_bh(&nss_gre_stats_lock);
+	for (i = 0; i < NSS_GRE_MAX_DEBUG_SESSION_STATS; i++) {
+		if (session_debug_stats[i].valid) {
+			memcpy(stats, &session_debug_stats[i], sizeof(struct nss_stats_gre_session_debug));
+			stats++;
+		}
+	}
+	spin_unlock_bh(&nss_gre_stats_lock);
+}
+
+/*
+ * nss_gre_base_debug_stats_get()
+ *	Get GRE debug base statistics.
+ */
+void nss_gre_base_debug_stats_get(void *stats_mem, int size)
+{
+	struct nss_stats_gre_base_debug *stats = (struct nss_stats_gre_base_debug *)stats_mem;
+
+	if (!stats) {
+		nss_warning("No memory to copy GRE base stats\n");
+		return;
+	}
+
+	if (size < sizeof(struct nss_stats_gre_base_debug)) {
+		nss_warning("Not enough memory to copy GRE base stats\n");
+		return;
+	}
+
+	spin_lock_bh(&nss_gre_stats_lock);
+	memcpy(stats, &base_debug_stats, sizeof(struct nss_stats_gre_base_debug));
+	spin_unlock_bh(&nss_gre_stats_lock);
+}
+
+/*
+ * nss_gre_register_pkt_callback()
+ *	Register for data callback.
+ */
+void nss_gre_register_pkt_callback(nss_gre_pkt_callback_t cb)
+{
+	atomic64_set(&pkt_cb_addr, (unsigned long)cb);
+}
+EXPORT_SYMBOL(nss_gre_register_pkt_callback);
+
+/*
+ * nss_gre_unregister_pkt_callback()
+ *	Unregister for data callback.
+ */
+void nss_gre_unregister_pkt_callback()
+{
+	atomic64_set(&pkt_cb_addr, 0);
+}
+EXPORT_SYMBOL(nss_gre_unregister_pkt_callback);
+
+/*
  * nss_gre_tx_msg()
  *	Transmit a GRE message to NSS firmware
  */
@@ -359,7 +402,7 @@
  * nss_gre_register_if()
  *	Register data and message handlers for GRE.
  */
-struct nss_ctx_instance *nss_gre_register_if(uint32_t if_num, nss_gre_data_callback_t gre_callback,
+struct nss_ctx_instance *nss_gre_register_if(uint32_t if_num, nss_gre_data_callback_t data_callback,
 			nss_gre_msg_callback_t event_callback, struct net_device *netdev, uint32_t features)
 {
 	struct nss_ctx_instance *nss_ctx = (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.gre_handler_id];
@@ -369,11 +412,12 @@
 	nss_assert(nss_is_dynamic_interface(if_num));
 
 	nss_ctx->subsys_dp_register[if_num].ndev = netdev;
-	nss_ctx->subsys_dp_register[if_num].cb = gre_callback;
+	nss_ctx->subsys_dp_register[if_num].cb = nss_gre_rx_handler;
 	nss_ctx->subsys_dp_register[if_num].app_data = netdev;
 	nss_ctx->subsys_dp_register[if_num].features = features;
 
 	nss_top_main.gre_msg_callback = event_callback;
+	nss_top_main.gre_data_callback = data_callback;
 
 	nss_core_register_handler(if_num, nss_gre_msg_handler, NULL);