From 1e43e60aa7ae118309cf256c50bd17f313540eba Mon Sep 17 00:00:00 2001
From: Xiang Xiao <xiaoxiang@xiaomi.com>
Date: Mon, 7 Jan 2019 02:15:42 +0800
Subject: [PATCH 01/10] ns: acknowledge the received creation message

the two phase handsake make the client could initiate the transfer
immediately without the server side send any dummy message first.

Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
---
 lib/include/openamp/rpmsg.h        |  1 +
 lib/include/openamp/rpmsg_virtio.h |  1 +
 lib/rpmsg/rpmsg.c                  |  5 ++++-
 lib/rpmsg/rpmsg_internal.h         |  4 ++--
 lib/rpmsg/rpmsg_virtio.c           | 15 ++++++++++++---
 5 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/lib/include/openamp/rpmsg.h open-amp/lib/include/openamp/rpmsg.h
index 64678cfc..ff3ff8fb 100644
--- a/lib/include/openamp/rpmsg.h
+++ open-amp/lib/include/openamp/rpmsg.h
@@ -126,6 +126,7 @@ struct rpmsg_device {
 	rpmsg_ns_bind_cb ns_unbind_cb;
 	struct rpmsg_device_ops ops;
 	bool support_ns;
+	bool support_ack;
 };
 
 /**
diff --git a/lib/include/openamp/rpmsg_virtio.h open-amp/lib/include/openamp/rpmsg_virtio.h
index 80ce9981..874c9723 100644
--- a/lib/include/openamp/rpmsg_virtio.h
+++ open-amp/lib/include/openamp/rpmsg_virtio.h
@@ -28,6 +28,7 @@ extern "C" {
 
 /* The feature bitmap for virtio rpmsg */
 #define VIRTIO_RPMSG_F_NS	0 /* RP supports name service notifications */
+#define VIRTIO_RPMSG_F_ACK	1 /* RP supports name service acknowledge */
 
 /**
  * struct rpmsg_virtio_shm_pool - shared memory pool used for rpmsg buffers
diff --git a/lib/rpmsg/rpmsg.c open-amp/lib/rpmsg/rpmsg.c
index 0d3e1d03..e8757d80 100644
--- a/lib/rpmsg/rpmsg.c
+++ open-amp/lib/rpmsg/rpmsg.c
@@ -317,10 +317,13 @@ int rpmsg_create_ept(struct rpmsg_endpoint *ept, struct rpmsg_device *rdev,
 	rpmsg_register_endpoint(rdev, ept, name, addr, dest, cb, unbind_cb);
 	metal_mutex_release(&rdev->lock);
 
-	/* Send NS announcement to remote processor */
+	/* Send NS announcement/acknowledge to remote processor */
 	if (ept->name[0] && rdev->support_ns &&
 	    ept->dest_addr == RPMSG_ADDR_ANY)
 		status = rpmsg_send_ns_message(ept, RPMSG_NS_CREATE);
+	else if (ept->name[0] && rdev->support_ack &&
+		 ept->dest_addr != RPMSG_ADDR_ANY)
+		status = rpmsg_send_ns_message(ept, RPMSG_NS_CREATE_ACK);
 
 	if (status)
 		rpmsg_unregister_endpoint(ept);
diff --git a/lib/rpmsg/rpmsg_internal.h open-amp/lib/rpmsg/rpmsg_internal.h
index ab6e0f29..3e6ae37f 100644
--- a/lib/rpmsg/rpmsg_internal.h
+++ open-amp/lib/rpmsg/rpmsg_internal.h
@@ -39,12 +39,12 @@ extern "C" {
  *
  * @RPMSG_NS_CREATE: a new remote service was just created
  * @RPMSG_NS_DESTROY: a known remote service was just destroyed
- * @RPMSG_NS_CREATE_WITH_ACK: a new remote service was just created waiting
- *                            acknowledgment.
+ * @RPMSG_NS_CREATE_ACK: acknowledge the previous creation message
  */
 enum rpmsg_ns_flags {
 	RPMSG_NS_CREATE = 0,
 	RPMSG_NS_DESTROY = 1,
+	RPMSG_NS_CREATE_ACK = 2,
 };
 
 /**
diff --git a/lib/rpmsg/rpmsg_virtio.c open-amp/lib/rpmsg/rpmsg_virtio.c
index cab72e68..5726c2ca 100644
--- a/lib/rpmsg/rpmsg_virtio.c
+++ open-amp/lib/rpmsg/rpmsg_virtio.c
@@ -638,7 +638,7 @@ static int rpmsg_virtio_ns_callback(struct rpmsg_endpoint *ept, void *data,
 	metal_mutex_acquire(&rdev->lock);
 	_ept = rpmsg_get_endpoint(rdev, name, RPMSG_ADDR_ANY, dest);
 
-	if (ns_msg->flags & RPMSG_NS_DESTROY) {
+	if (ns_msg->flags == RPMSG_NS_DESTROY) {
 		if (_ept)
 			_ept->dest_addr = RPMSG_ADDR_ANY;
 		metal_mutex_release(&rdev->lock);
@@ -646,7 +646,7 @@ static int rpmsg_virtio_ns_callback(struct rpmsg_endpoint *ept, void *data,
 			_ept->ns_unbind_cb(_ept);
 		if (rdev->ns_unbind_cb)
 			rdev->ns_unbind_cb(rdev, name, dest);
-	} else {
+	} else if (ns_msg->flags == RPMSG_NS_CREATE) {
 		if (!_ept) {
 			/*
 			 * send callback to application, that can
@@ -660,7 +660,15 @@ static int rpmsg_virtio_ns_callback(struct rpmsg_endpoint *ept, void *data,
 		} else {
 			_ept->dest_addr = dest;
 			metal_mutex_release(&rdev->lock);
+			if (_ept->name[0] && rdev->support_ack)
+				rpmsg_send_ns_message(_ept,
+						      RPMSG_NS_CREATE_ACK);
 		}
+	} else { /* RPMSG_NS_CREATE_ACK */
+		/* save the received destination address */
+		if (_ept)
+			_ept->dest_addr = dest;
+		metal_mutex_release(&rdev->lock);
 	}
 
 	return RPMSG_SUCCESS;
@@ -745,6 +753,7 @@ int rpmsg_init_vdev_with_config(struct rpmsg_virtio_device *rvdev,
 #endif /*!VIRTIO_DRIVER_ONLY*/
 	vdev->features = rpmsg_virtio_get_features(rvdev);
 	rdev->support_ns = !!(vdev->features & (1 << VIRTIO_RPMSG_F_NS));
+	rdev->support_ack = !!(vdev->features & (1 << VIRTIO_RPMSG_F_ACK));
 
 #ifndef VIRTIO_DEVICE_ONLY
 	if (role == RPMSG_HOST) {
@@ -841,7 +850,7 @@ int rpmsg_init_vdev_with_config(struct rpmsg_virtio_device *rvdev,
 	 * Create name service announcement endpoint if device supports name
 	 * service announcement feature.
 	 */
-	if (rdev->support_ns) {
+	if (rdev->support_ns || rdev->support_ack) {
 		rpmsg_register_endpoint(rdev, &rdev->ns_ept, "NS",
 				     RPMSG_NS_EPT_ADDR, RPMSG_NS_EPT_ADDR,
 				     rpmsg_virtio_ns_callback, NULL);
-- 
2.25.1