Merge "[qca-nss-drv]: Register the callback for ptp service code"
diff --git a/exports/nss_cmn.h b/exports/nss_cmn.h
index 33bb6b5..851df6e 100644
--- a/exports/nss_cmn.h
+++ b/exports/nss_cmn.h
@@ -372,6 +372,57 @@
 extern nss_cb_unregister_status_t nss_cmn_unregister_queue_decongestion(struct nss_ctx_instance *nss_ctx, nss_cmn_queue_decongestion_callback_t event_callback);
 
 /**
+ * Callback function for packets with service code.
+ *
+ * @param[in] app_data  Pointer to the application context for this message.
+ * @param[in] nbuf      Pointer to the socket buffer.
+ */
+typedef void (*nss_cmn_service_code_callback_t)(void *app_data, struct sk_buff *nbuf);
+
+/**
+ * nss_cmn_register_service_code
+ *	Registers a callback for a service code.
+ *
+ * @datatypes
+ * nss_ctx_instance \n
+ * nss_cmn_service_code_callback_t
+ *
+ * @param[in,out] nss_ctx         Pointer to the NSS context.
+ * @param[in]     cb              Callback for the message.
+ * @param[in]     service_code    Service code found attached to the packet.
+ * @param[in]     app_data        Pointer to the application context to be returned in the
+ *                                callback.
+ *
+ * @return
+ * #NSS_CB_REGISTER_SUCCESS if registration is successful.
+ * @par
+ * Otherwise, #NSS_CB_REGISTER_FAILED.
+ */
+extern nss_cb_register_status_t nss_cmn_register_service_code(struct nss_ctx_instance *nss_ctx, nss_cmn_service_code_callback_t cb, uint8_t service_code, void *app_data);
+
+/**
+ * nss_cmn_unregister_service_code
+ *	Deregisters a callback for the given service code.
+ *
+ * @datatypes
+ * nss_ctx_instance \n
+ * nss_cmn_service_code_callback_t
+ *
+ * @param[in,out] nss_ctx         Pointer to the NSS context.
+ * @param[in]     cb              Callback for the message.
+ * @param[in]     service_code    Service code found attached to the packet.
+ *
+ * @return
+ * #NSS_CB_REGISTER_SUCCESS if registration is successful.
+ * @par
+ * Otherwise, #NSS_CB_REGISTER_FAILED.
+ *
+ * @dependencies
+ * The callback function must have been previously registered.
+ */
+extern nss_cb_unregister_status_t nss_cmn_unregister_service_code(struct nss_ctx_instance *nss_ctx, nss_cmn_service_code_callback_t cb, uint8_t service_code);
+
+/**
  * nss_cmn_get_nss_enabled
  *	Checks whether the NSS mode is supported on the platform.
  *
diff --git a/nss_cmn.c b/nss_cmn.c
index 4f887e5..920aca2 100644
--- a/nss_cmn.c
+++ b/nss_cmn.c
@@ -75,7 +75,7 @@
 
 	NSS_VERIFY_CTX_MAGIC(nss_ctx);
 	if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
-		nss_warning("%p: Interface number could not be found as core not ready", nss_ctx);
+		nss_warning("%p: Interface number could not be found as core not ready\n", nss_ctx);
 		return -1;
 	}
 
@@ -90,7 +90,7 @@
 		}
 	}
 
-	nss_warning("%p: Interface number could not be found as interface has not registered yet", nss_ctx);
+	nss_warning("%p: Interface number could not be found as interface has not registered yet\n", nss_ctx);
 	return -1;
 }
 EXPORT_SYMBOL(nss_cmn_get_interface_number);
@@ -107,7 +107,7 @@
 
 	NSS_VERIFY_CTX_MAGIC(nss_ctx);
 	if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
-		nss_warning("%p: Interface device could not be found as core not ready", nss_ctx);
+		nss_warning("%p: Interface device could not be found as core not ready\n", nss_ctx);
 		return NULL;
 	}
 
@@ -140,7 +140,7 @@
 		}
 	}
 
-	nss_warning("Interface number could not be found for %p (%s) as interface has not registered yet", dev, dev->name);
+	nss_warning("Interface number could not be found for %p (%s) as interface has not registered yet\n", dev, dev->name);
 	return -1;
 }
 EXPORT_SYMBOL(nss_cmn_get_interface_number_by_dev_and_type);
@@ -264,6 +264,51 @@
 EXPORT_SYMBOL(nss_cmn_unregister_queue_decongestion);
 
 /*
+ * nss_cmn_register_service_code()
+ *	Register for service code event
+ */
+nss_cb_register_status_t nss_cmn_register_service_code(struct nss_ctx_instance *nss_ctx, nss_cmn_service_code_callback_t cb, uint8_t service_code, void *app_data)
+{
+	NSS_VERIFY_CTX_MAGIC(nss_ctx);
+
+	if (nss_ctx->service_code_callback[service_code]) {
+		/*
+		 * We already have a callback registered for this service code.
+		 */
+		nss_warning("%p: a callback is registered already for this service code %d\n", nss_ctx, service_code);
+
+		return NSS_CB_REGISTER_FAILED;
+	}
+
+	nss_ctx->service_code_callback[service_code] = cb;
+	nss_ctx->service_code_ctx[service_code] = app_data;
+	return NSS_CB_REGISTER_SUCCESS;
+}
+EXPORT_SYMBOL(nss_cmn_register_service_code);
+
+/*
+ * nss_cmn_unregister_service_code()
+ *	Unregister for service code event
+ */
+nss_cb_unregister_status_t nss_cmn_unregister_service_code(struct nss_ctx_instance *nss_ctx, nss_cmn_service_code_callback_t cb, uint8_t service_code)
+{
+	NSS_VERIFY_CTX_MAGIC(nss_ctx);
+
+	if (!nss_ctx->service_code_callback[service_code]) {
+		/*
+		 * No callback was registered for this service code.
+		 */
+		nss_warning("%p: no callback is registered for this service code %d\n", nss_ctx, service_code);
+		return NSS_CB_UNREGISTER_FAILED;
+	}
+
+	nss_ctx->service_code_callback[service_code] = NULL;
+	nss_ctx->service_code_ctx[service_code] = NULL;
+	return NSS_CB_UNREGISTER_SUCCESS;
+}
+EXPORT_SYMBOL(nss_cmn_unregister_service_code);
+
+/*
  * nss_cmn_get_nss_enabled()
  * 	Check if NSS mode is supported on platform
  *
diff --git a/nss_core.c b/nss_core.c
index 8827a7d..28b1de6 100644
--- a/nss_core.c
+++ b/nss_core.c
@@ -705,7 +705,7 @@
 						unsigned int interface_num,
 						struct sk_buff *nbuf,
 						struct napi_struct *napi,
-						uint16_t flags, uint16_t qid)
+						uint16_t flags, uint16_t qid, uint8_t service_code)
 {
 	struct nss_top_instance *nss_top = nss_ctx->nss_top;
 	struct nss_subsystem_dataplane_register *subsys_dp_reg = &nss_ctx->subsys_dp_register[interface_num];
@@ -730,6 +730,23 @@
 	}
 
 	/*
+	 * If we have a non-zero service code, call the corresponding service code
+	 * callback. The callback will consume the skb.
+	 * For service code, we provide the raw packet as it was received.
+	 */
+	if (unlikely(service_code)) {
+		nss_cmn_service_code_callback_t cb = nss_ctx->service_code_callback[service_code];
+		if (likely(cb)) {
+			dev_hold(ndev);
+			nbuf->dev = ndev;
+			nbuf->protocol = eth_type_trans(nbuf, ndev);
+			cb(nss_ctx->service_code_ctx[service_code], nbuf);
+			dev_put(ndev);
+			return;
+		}
+	}
+
+	/*
 	 * Deliver nbuf to the interface through callback if there is one.
 	 */
 	cb = subsys_dp_reg->cb;
@@ -811,7 +828,8 @@
  *	Receive a pbuf from the NSS into Linux.
  */
 static inline void nss_core_rx_pbuf(struct nss_ctx_instance *nss_ctx, struct napi_struct *napi,
-				uint8_t buffer_type, struct sk_buff *nbuf, uint32_t desc_ifnum, uint32_t bit_flags, uint16_t qid)
+				uint8_t buffer_type, struct sk_buff *nbuf, uint32_t desc_ifnum,
+				uint32_t bit_flags, uint16_t qid, uint8_t service_code)
 {
 	unsigned int interface_num = NSS_INTERFACE_NUM_GET(desc_ifnum);
 	unsigned int core_id = NSS_INTERFACE_NUM_GET_COREID(desc_ifnum);
@@ -854,7 +872,7 @@
 		break;
 
 	case N2H_BUFFER_PACKET:
-		nss_core_handle_buffer_pkt(nss_ctx, interface_num, nbuf, napi, bit_flags, qid);
+		nss_core_handle_buffer_pkt(nss_ctx, interface_num, nbuf, napi, bit_flags, qid, service_code);
 		break;
 
 	case N2H_BUFFER_PACKET_EXT:
@@ -1462,7 +1480,7 @@
 		}
 
 consume:
-		nss_core_rx_pbuf(nss_ctx, &(int_ctx->napi), buffer_type, nbuf, n2h_desc_ring->interface_num, n2h_desc_ring->bit_flags, qid);
+		nss_core_rx_pbuf(nss_ctx, &(int_ctx->napi), buffer_type, nbuf, n2h_desc_ring->interface_num, n2h_desc_ring->bit_flags, qid, desc->service_code);
 
 next:
 
diff --git a/nss_core.h b/nss_core.h
index 43dd816..6756d05 100644
--- a/nss_core.h
+++ b/nss_core.h
@@ -209,6 +209,11 @@
 #define NSS_MAX_CLIENTS 12
 
 /*
+ * Maximum number of service code NSS supports
+ */
+#define NSS_MAX_SERVICE_CODE 256
+
+/*
  * Interrupt cause processing weights
  */
 #define NSS_EMPTY_BUFFER_SOS_PROCESSING_WEIGHT 64
@@ -518,6 +523,10 @@
 					/* Queue decongestion callbacks */
 	void *queue_decongestion_ctx[NSS_MAX_CLIENTS];
 					/* Queue decongestion callback contexts */
+	nss_cmn_service_code_callback_t service_code_callback[NSS_MAX_SERVICE_CODE];
+					/* Service code callbacks */
+	void *service_code_ctx[NSS_MAX_SERVICE_CODE];
+					/* Service code callback contexts */
 	spinlock_t decongest_cb_lock;	/* Lock to protect queue decongestion cb table */
 	uint16_t phys_if_mtu[NSS_MAX_PHYSICAL_INTERFACES];
 					/* Current MTU value of physical interface */
diff --git a/nss_hlos_if.h b/nss_hlos_if.h
index 19b367d..f1188d9 100644
--- a/nss_hlos_if.h
+++ b/nss_hlos_if.h
@@ -280,7 +280,8 @@
 	uint8_t buffer_type;	/* Type of buffer */
 	uint8_t response_type;	/* Response type if the buffer is a command response */
 	uint8_t pri;		/* Packet priority */
-	uint8_t reserved[5];	/* Reserved for future use */
+	uint8_t service_code;	/* Service code */
+	uint32_t reserved;	/* Reserved for future use */
 	nss_ptr_t opaque;	/* 32 or 64-bit value provided by the HLOS to associate with the buffer. The cookie has no meaning to the NSS */
 #ifndef __LP64__
 	uint32_t padding;	/* Pad to fit 64 bits, do not reuse */