All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/14] Split rpmsg into a framework
@ 2016-08-16  0:17 ` Bjorn Andersson
  0 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-16  0:17 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson
  Cc: linux-remoteproc, linux-arm-msm, linux-arm-kernel, linux-kernel

This series splits the virtio rpmsg bus driver into a rpmsg bus and a virtio
backend/wireformat.


As we discussed the Qualcomm SMD implementation a couple of years back people
suggested that I should make it "a rpmsg thingie". With the introduction of the
Qualcomm 8996 platform, we must support a variant of the communication
mechanism that share many of the characteristics of SMD, but are different
enough that it can't be done in a single implementation. As such there is
enough benefit to do the necessary work and being able to make SMD a "rpmsg
thingie".

On-top of this series I have patches to switch the current smd clients over to
rpmsg (and by that drop the existing SMD implementation).

All this allows me to implement the new backend and reuse all existing SMD
drivers with the new mechanism.

Bjorn Andersson (14):
  rpmsg: Enable matching devices with drivers based on DT
  rpmsg: Name rpmsg devices based on channel id
  rpmsg: rpmsg_send() operations takes rpmsg_endpoint
  rpmsg: Internalize rpmsg_send() implementations
  rpmsg: Unify rpmsg device vs channel naming
  rpmsg: Indirect all virtio related function calls
  rpmsg: Split off generic tail of create_channel()
  rpmsg: Split rpmsg core and virtio backend
  rpmsg: Internalize rpmsg core ops
  rpmsg: virtio: Internalize vrp pointer
  rpmsg: Move virtio specifics from public header
  rpmsg: Make rpmsg_create_ept() take channel_info struct
  rpmsg: Allow callback to return errors
  rpmsg: Introduce Qualcomm SMD backend

 drivers/rpmsg/Kconfig            |   14 +
 drivers/rpmsg/Makefile           |    4 +-
 drivers/rpmsg/qcom_smd.c         | 1448 ++++++++++++++++++++++++++++++++++++++
 drivers/rpmsg/rpmsg_core.c       |  525 ++++++++++++++
 drivers/rpmsg/rpmsg_internal.h   |   63 ++
 drivers/rpmsg/virtio_rpmsg_bus.c |  483 +++++--------
 include/linux/rpmsg.h            |  242 +------
 7 files changed, 2268 insertions(+), 511 deletions(-)
 create mode 100644 drivers/rpmsg/qcom_smd.c
 create mode 100644 drivers/rpmsg/rpmsg_core.c
 create mode 100644 drivers/rpmsg/rpmsg_internal.h

-- 
2.5.0

^ permalink raw reply	[flat|nested] 54+ messages in thread

* [PATCH 00/14] Split rpmsg into a framework
@ 2016-08-16  0:17 ` Bjorn Andersson
  0 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-16  0:17 UTC (permalink / raw)
  To: linux-arm-kernel

This series splits the virtio rpmsg bus driver into a rpmsg bus and a virtio
backend/wireformat.


As we discussed the Qualcomm SMD implementation a couple of years back people
suggested that I should make it "a rpmsg thingie". With the introduction of the
Qualcomm 8996 platform, we must support a variant of the communication
mechanism that share many of the characteristics of SMD, but are different
enough that it can't be done in a single implementation. As such there is
enough benefit to do the necessary work and being able to make SMD a "rpmsg
thingie".

On-top of this series I have patches to switch the current smd clients over to
rpmsg (and by that drop the existing SMD implementation).

All this allows me to implement the new backend and reuse all existing SMD
drivers with the new mechanism.

Bjorn Andersson (14):
  rpmsg: Enable matching devices with drivers based on DT
  rpmsg: Name rpmsg devices based on channel id
  rpmsg: rpmsg_send() operations takes rpmsg_endpoint
  rpmsg: Internalize rpmsg_send() implementations
  rpmsg: Unify rpmsg device vs channel naming
  rpmsg: Indirect all virtio related function calls
  rpmsg: Split off generic tail of create_channel()
  rpmsg: Split rpmsg core and virtio backend
  rpmsg: Internalize rpmsg core ops
  rpmsg: virtio: Internalize vrp pointer
  rpmsg: Move virtio specifics from public header
  rpmsg: Make rpmsg_create_ept() take channel_info struct
  rpmsg: Allow callback to return errors
  rpmsg: Introduce Qualcomm SMD backend

 drivers/rpmsg/Kconfig            |   14 +
 drivers/rpmsg/Makefile           |    4 +-
 drivers/rpmsg/qcom_smd.c         | 1448 ++++++++++++++++++++++++++++++++++++++
 drivers/rpmsg/rpmsg_core.c       |  525 ++++++++++++++
 drivers/rpmsg/rpmsg_internal.h   |   63 ++
 drivers/rpmsg/virtio_rpmsg_bus.c |  483 +++++--------
 include/linux/rpmsg.h            |  242 +------
 7 files changed, 2268 insertions(+), 511 deletions(-)
 create mode 100644 drivers/rpmsg/qcom_smd.c
 create mode 100644 drivers/rpmsg/rpmsg_core.c
 create mode 100644 drivers/rpmsg/rpmsg_internal.h

-- 
2.5.0

^ permalink raw reply	[flat|nested] 54+ messages in thread

* [PATCH 01/14] rpmsg: Enable matching devices with drivers based on DT
  2016-08-16  0:17 ` Bjorn Andersson
  (?)
@ 2016-08-16  0:17   ` Bjorn Andersson
  -1 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-16  0:17 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson
  Cc: linux-remoteproc, linux-arm-msm, linux-arm-kernel, linux-kernel

Make it possible to match rpmsg devices based on device tree node, in
addition to the id table. In some of these cases the rpmsg driver would
not have a id_table, so make this optional.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/rpmsg/virtio_rpmsg_bus.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 4a4374cc6a59..495fa0a282d3 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -33,6 +33,7 @@
 #include <linux/wait.h>
 #include <linux/rpmsg.h>
 #include <linux/mutex.h>
+#include <linux/of_device.h>
 
 /**
  * struct virtproc_info - virtual remote processor state
@@ -175,11 +176,12 @@ static int rpmsg_dev_match(struct device *dev, struct device_driver *drv)
 	const struct rpmsg_device_id *ids = rpdrv->id_table;
 	unsigned int i;
 
-	for (i = 0; ids[i].name[0]; i++)
-		if (rpmsg_id_match(rpdev, &ids[i]))
-			return 1;
+	if (ids)
+		for (i = 0; ids[i].name[0]; i++)
+			if (rpmsg_id_match(rpdev, &ids[i]))
+				return 1;
 
-	return 0;
+	return of_driver_match_device(dev, drv);
 }
 
 static int rpmsg_uevent(struct device *dev, struct kobj_uevent_env *env)
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 01/14] rpmsg: Enable matching devices with drivers based on DT
@ 2016-08-16  0:17   ` Bjorn Andersson
  0 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-16  0:17 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson
  Cc: linux-arm-msm, linux-remoteproc, linux-kernel, linux-arm-kernel

Make it possible to match rpmsg devices based on device tree node, in
addition to the id table. In some of these cases the rpmsg driver would
not have a id_table, so make this optional.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/rpmsg/virtio_rpmsg_bus.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 4a4374cc6a59..495fa0a282d3 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -33,6 +33,7 @@
 #include <linux/wait.h>
 #include <linux/rpmsg.h>
 #include <linux/mutex.h>
+#include <linux/of_device.h>
 
 /**
  * struct virtproc_info - virtual remote processor state
@@ -175,11 +176,12 @@ static int rpmsg_dev_match(struct device *dev, struct device_driver *drv)
 	const struct rpmsg_device_id *ids = rpdrv->id_table;
 	unsigned int i;
 
-	for (i = 0; ids[i].name[0]; i++)
-		if (rpmsg_id_match(rpdev, &ids[i]))
-			return 1;
+	if (ids)
+		for (i = 0; ids[i].name[0]; i++)
+			if (rpmsg_id_match(rpdev, &ids[i]))
+				return 1;
 
-	return 0;
+	return of_driver_match_device(dev, drv);
 }
 
 static int rpmsg_uevent(struct device *dev, struct kobj_uevent_env *env)
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 01/14] rpmsg: Enable matching devices with drivers based on DT
@ 2016-08-16  0:17   ` Bjorn Andersson
  0 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-16  0:17 UTC (permalink / raw)
  To: linux-arm-kernel

Make it possible to match rpmsg devices based on device tree node, in
addition to the id table. In some of these cases the rpmsg driver would
not have a id_table, so make this optional.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/rpmsg/virtio_rpmsg_bus.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 4a4374cc6a59..495fa0a282d3 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -33,6 +33,7 @@
 #include <linux/wait.h>
 #include <linux/rpmsg.h>
 #include <linux/mutex.h>
+#include <linux/of_device.h>
 
 /**
  * struct virtproc_info - virtual remote processor state
@@ -175,11 +176,12 @@ static int rpmsg_dev_match(struct device *dev, struct device_driver *drv)
 	const struct rpmsg_device_id *ids = rpdrv->id_table;
 	unsigned int i;
 
-	for (i = 0; ids[i].name[0]; i++)
-		if (rpmsg_id_match(rpdev, &ids[i]))
-			return 1;
+	if (ids)
+		for (i = 0; ids[i].name[0]; i++)
+			if (rpmsg_id_match(rpdev, &ids[i]))
+				return 1;
 
-	return 0;
+	return of_driver_match_device(dev, drv);
 }
 
 static int rpmsg_uevent(struct device *dev, struct kobj_uevent_env *env)
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 02/14] rpmsg: Name rpmsg devices based on channel id
  2016-08-16  0:17 ` Bjorn Andersson
@ 2016-08-16  0:17   ` Bjorn Andersson
  -1 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-16  0:17 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson
  Cc: linux-remoteproc, linux-arm-msm, linux-arm-kernel, linux-kernel

By basing rpmsg device names on channel id we end up with human readable
device names in sysfs and debug logs.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/rpmsg/virtio_rpmsg_bus.c | 12 ++----------
 1 file changed, 2 insertions(+), 10 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 495fa0a282d3..c4bd89ea7681 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -136,14 +136,6 @@ rpmsg_show_attr(src, src, "0x%x\n");
 rpmsg_show_attr(dst, dst, "0x%x\n");
 rpmsg_show_attr(announce, announce ? "true" : "false", "%s\n");
 
-/*
- * Unique (and free running) index for rpmsg devices.
- *
- * Yeah, we're not recycling those numbers (yet?). will be easy
- * to change if/when we want to.
- */
-static unsigned int rpmsg_dev_index;
-
 static ssize_t modalias_show(struct device *dev,
 			     struct device_attribute *attr, char *buf)
 {
@@ -531,8 +523,8 @@ static struct rpmsg_channel *rpmsg_create_channel(struct virtproc_info *vrp,
 
 	strncpy(rpdev->id.name, chinfo->name, RPMSG_NAME_SIZE);
 
-	/* very simple device indexing plumbing which is enough for now */
-	dev_set_name(&rpdev->dev, "rpmsg%d", rpmsg_dev_index++);
+	dev_set_name(&rpdev->dev, "%s:%s",
+		     dev_name(dev->parent), rpdev->id.name);
 
 	rpdev->dev.parent = &vrp->vdev->dev;
 	rpdev->dev.bus = &rpmsg_bus;
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 02/14] rpmsg: Name rpmsg devices based on channel id
@ 2016-08-16  0:17   ` Bjorn Andersson
  0 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-16  0:17 UTC (permalink / raw)
  To: linux-arm-kernel

By basing rpmsg device names on channel id we end up with human readable
device names in sysfs and debug logs.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/rpmsg/virtio_rpmsg_bus.c | 12 ++----------
 1 file changed, 2 insertions(+), 10 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 495fa0a282d3..c4bd89ea7681 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -136,14 +136,6 @@ rpmsg_show_attr(src, src, "0x%x\n");
 rpmsg_show_attr(dst, dst, "0x%x\n");
 rpmsg_show_attr(announce, announce ? "true" : "false", "%s\n");
 
-/*
- * Unique (and free running) index for rpmsg devices.
- *
- * Yeah, we're not recycling those numbers (yet?). will be easy
- * to change if/when we want to.
- */
-static unsigned int rpmsg_dev_index;
-
 static ssize_t modalias_show(struct device *dev,
 			     struct device_attribute *attr, char *buf)
 {
@@ -531,8 +523,8 @@ static struct rpmsg_channel *rpmsg_create_channel(struct virtproc_info *vrp,
 
 	strncpy(rpdev->id.name, chinfo->name, RPMSG_NAME_SIZE);
 
-	/* very simple device indexing plumbing which is enough for now */
-	dev_set_name(&rpdev->dev, "rpmsg%d", rpmsg_dev_index++);
+	dev_set_name(&rpdev->dev, "%s:%s",
+		     dev_name(dev->parent), rpdev->id.name);
 
 	rpdev->dev.parent = &vrp->vdev->dev;
 	rpdev->dev.bus = &rpmsg_bus;
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 03/14] rpmsg: rpmsg_send() operations takes rpmsg_endpoint
  2016-08-16  0:17 ` Bjorn Andersson
  (?)
@ 2016-08-16  0:17   ` Bjorn Andersson
  -1 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-16  0:17 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson
  Cc: linux-remoteproc, linux-arm-msm, linux-arm-kernel, linux-kernel

The rpmsg_send() operations has been taking a rpmsg_device, but this
forces users of secondary rpmsg_endpoints to use the rpmsg_sendto()
interface - by extracting source and destination from the given data
structures. If we instead pass the rpmsg_endpoint to these functions a
service can use rpmsg_sendto() to respond to messages, even on secondary
endpoints.

In addition this would allow us to support operations on multiple
channels in future backends that does not support off-channel
operations.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/rpmsg/virtio_rpmsg_bus.c |  4 +--
 include/linux/rpmsg.h            | 70 +++++++++++++++++++++++-----------------
 2 files changed, 42 insertions(+), 32 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index c4bd89ea7681..1b63f4b7c2bd 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -382,7 +382,7 @@ static int rpmsg_dev_probe(struct device *dev)
 		nsm.addr = rpdev->src;
 		nsm.flags = RPMSG_NS_CREATE;
 
-		err = rpmsg_sendto(rpdev, &nsm, sizeof(nsm), RPMSG_NS_ADDR);
+		err = rpmsg_sendto(rpdev->ept, &nsm, sizeof(nsm), RPMSG_NS_ADDR);
 		if (err)
 			dev_err(dev, "failed to announce service %d\n", err);
 	}
@@ -407,7 +407,7 @@ static int rpmsg_dev_remove(struct device *dev)
 		nsm.addr = rpdev->src;
 		nsm.flags = RPMSG_NS_DESTROY;
 
-		err = rpmsg_sendto(rpdev, &nsm, sizeof(nsm), RPMSG_NS_ADDR);
+		err = rpmsg_sendto(rpdev->ept, &nsm, sizeof(nsm), RPMSG_NS_ADDR);
 		if (err)
 			dev_err(dev, "failed to announce service %d\n", err);
 	}
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index 2b97c711a5e3..88e302c011e6 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -193,13 +193,14 @@ rpmsg_send_offchannel_raw(struct rpmsg_channel *, u32, u32, void *, int, bool);
 
 /**
  * rpmsg_send() - send a message across to the remote processor
- * @rpdev: the rpmsg channel
+ * @ept: the rpmsg endpoint
  * @data: payload of message
  * @len: length of payload
  *
- * This function sends @data of length @len on the @rpdev channel.
- * The message will be sent to the remote processor which the @rpdev
- * channel belongs to, using @rpdev's source and destination addresses.
+ * This function sends @data of length @len on the @ept endpoint.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to, using @ept's address and its associated rpmsg
+ * device destination addresses.
  * In case there are no TX buffers available, the function will block until
  * one becomes available, or a timeout of 15 seconds elapses. When the latter
  * happens, -ERESTARTSYS is returned.
@@ -208,23 +209,24 @@ rpmsg_send_offchannel_raw(struct rpmsg_channel *, u32, u32, void *, int, bool);
  *
  * Returns 0 on success and an appropriate error value on failure.
  */
-static inline int rpmsg_send(struct rpmsg_channel *rpdev, void *data, int len)
+static inline int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
 {
-	u32 src = rpdev->src, dst = rpdev->dst;
+	struct rpmsg_channel *rpdev = ept->rpdev;
+	u32 src = ept->addr, dst = rpdev->dst;
 
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
 }
 
 /**
  * rpmsg_sendto() - send a message across to the remote processor, specify dst
- * @rpdev: the rpmsg channel
+ * @ept: the rpmsg endpoint
  * @data: payload of message
  * @len: length of payload
  * @dst: destination address
  *
  * This function sends @data of length @len to the remote @dst address.
- * The message will be sent to the remote processor which the @rpdev
- * channel belongs to, using @rpdev's source address.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to, using @ept's address as source.
  * In case there are no TX buffers available, the function will block until
  * one becomes available, or a timeout of 15 seconds elapses. When the latter
  * happens, -ERESTARTSYS is returned.
@@ -234,16 +236,17 @@ static inline int rpmsg_send(struct rpmsg_channel *rpdev, void *data, int len)
  * Returns 0 on success and an appropriate error value on failure.
  */
 static inline
-int rpmsg_sendto(struct rpmsg_channel *rpdev, void *data, int len, u32 dst)
+int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
 {
-	u32 src = rpdev->src;
+	struct rpmsg_channel *rpdev = ept->rpdev;
+	u32 src = ept->addr;
 
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
 }
 
 /**
  * rpmsg_send_offchannel() - send a message using explicit src/dst addresses
- * @rpdev: the rpmsg channel
+ * @ept: the rpmsg endpoint
  * @src: source address
  * @dst: destination address
  * @data: payload of message
@@ -251,8 +254,8 @@ int rpmsg_sendto(struct rpmsg_channel *rpdev, void *data, int len, u32 dst)
  *
  * This function sends @data of length @len to the remote @dst address,
  * and uses @src as the source address.
- * The message will be sent to the remote processor which the @rpdev
- * channel belongs to.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to.
  * In case there are no TX buffers available, the function will block until
  * one becomes available, or a timeout of 15 seconds elapses. When the latter
  * happens, -ERESTARTSYS is returned.
@@ -262,21 +265,24 @@ int rpmsg_sendto(struct rpmsg_channel *rpdev, void *data, int len, u32 dst)
  * Returns 0 on success and an appropriate error value on failure.
  */
 static inline
-int rpmsg_send_offchannel(struct rpmsg_channel *rpdev, u32 src, u32 dst,
+int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
 			  void *data, int len)
 {
+	struct rpmsg_channel *rpdev = ept->rpdev;
+
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
 }
 
 /**
  * rpmsg_send() - send a message across to the remote processor
- * @rpdev: the rpmsg channel
+ * @ept: the rpmsg endpoint
  * @data: payload of message
  * @len: length of payload
  *
- * This function sends @data of length @len on the @rpdev channel.
- * The message will be sent to the remote processor which the @rpdev
- * channel belongs to, using @rpdev's source and destination addresses.
+ * This function sends @data of length @len on the @ept endpoint.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to, using @ept's addres as source and its associated
+ * rpdev's address as destination.
  * In case there are no TX buffers available, the function will immediately
  * return -ENOMEM without waiting until one becomes available.
  *
@@ -285,23 +291,24 @@ int rpmsg_send_offchannel(struct rpmsg_channel *rpdev, u32 src, u32 dst,
  * Returns 0 on success and an appropriate error value on failure.
  */
 static inline
-int rpmsg_trysend(struct rpmsg_channel *rpdev, void *data, int len)
+int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
 {
-	u32 src = rpdev->src, dst = rpdev->dst;
+	struct rpmsg_channel *rpdev = ept->rpdev;
+	u32 src = ept->addr, dst = rpdev->dst;
 
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
 }
 
 /**
  * rpmsg_sendto() - send a message across to the remote processor, specify dst
- * @rpdev: the rpmsg channel
+ * @ept: the rpmsg endpoint
  * @data: payload of message
  * @len: length of payload
  * @dst: destination address
  *
  * This function sends @data of length @len to the remote @dst address.
- * The message will be sent to the remote processor which the @rpdev
- * channel belongs to, using @rpdev's source address.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to, using @ept's address as source.
  * In case there are no TX buffers available, the function will immediately
  * return -ENOMEM without waiting until one becomes available.
  *
@@ -310,16 +317,17 @@ int rpmsg_trysend(struct rpmsg_channel *rpdev, void *data, int len)
  * Returns 0 on success and an appropriate error value on failure.
  */
 static inline
-int rpmsg_trysendto(struct rpmsg_channel *rpdev, void *data, int len, u32 dst)
+int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
 {
-	u32 src = rpdev->src;
+	struct rpmsg_channel *rpdev = ept->rpdev;
+	u32 src = ept->addr;
 
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
 }
 
 /**
  * rpmsg_send_offchannel() - send a message using explicit src/dst addresses
- * @rpdev: the rpmsg channel
+ * @ept: the rpmsg endpoint
  * @src: source address
  * @dst: destination address
  * @data: payload of message
@@ -327,8 +335,8 @@ int rpmsg_trysendto(struct rpmsg_channel *rpdev, void *data, int len, u32 dst)
  *
  * This function sends @data of length @len to the remote @dst address,
  * and uses @src as the source address.
- * The message will be sent to the remote processor which the @rpdev
- * channel belongs to.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to.
  * In case there are no TX buffers available, the function will immediately
  * return -ENOMEM without waiting until one becomes available.
  *
@@ -337,9 +345,11 @@ int rpmsg_trysendto(struct rpmsg_channel *rpdev, void *data, int len, u32 dst)
  * Returns 0 on success and an appropriate error value on failure.
  */
 static inline
-int rpmsg_trysend_offchannel(struct rpmsg_channel *rpdev, u32 src, u32 dst,
+int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
 			     void *data, int len)
 {
+	struct rpmsg_channel *rpdev = ept->rpdev;
+
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
 }
 
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 03/14] rpmsg: rpmsg_send() operations takes rpmsg_endpoint
@ 2016-08-16  0:17   ` Bjorn Andersson
  0 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-16  0:17 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson
  Cc: linux-arm-msm, linux-remoteproc, linux-kernel, linux-arm-kernel

The rpmsg_send() operations has been taking a rpmsg_device, but this
forces users of secondary rpmsg_endpoints to use the rpmsg_sendto()
interface - by extracting source and destination from the given data
structures. If we instead pass the rpmsg_endpoint to these functions a
service can use rpmsg_sendto() to respond to messages, even on secondary
endpoints.

In addition this would allow us to support operations on multiple
channels in future backends that does not support off-channel
operations.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/rpmsg/virtio_rpmsg_bus.c |  4 +--
 include/linux/rpmsg.h            | 70 +++++++++++++++++++++++-----------------
 2 files changed, 42 insertions(+), 32 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index c4bd89ea7681..1b63f4b7c2bd 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -382,7 +382,7 @@ static int rpmsg_dev_probe(struct device *dev)
 		nsm.addr = rpdev->src;
 		nsm.flags = RPMSG_NS_CREATE;
 
-		err = rpmsg_sendto(rpdev, &nsm, sizeof(nsm), RPMSG_NS_ADDR);
+		err = rpmsg_sendto(rpdev->ept, &nsm, sizeof(nsm), RPMSG_NS_ADDR);
 		if (err)
 			dev_err(dev, "failed to announce service %d\n", err);
 	}
@@ -407,7 +407,7 @@ static int rpmsg_dev_remove(struct device *dev)
 		nsm.addr = rpdev->src;
 		nsm.flags = RPMSG_NS_DESTROY;
 
-		err = rpmsg_sendto(rpdev, &nsm, sizeof(nsm), RPMSG_NS_ADDR);
+		err = rpmsg_sendto(rpdev->ept, &nsm, sizeof(nsm), RPMSG_NS_ADDR);
 		if (err)
 			dev_err(dev, "failed to announce service %d\n", err);
 	}
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index 2b97c711a5e3..88e302c011e6 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -193,13 +193,14 @@ rpmsg_send_offchannel_raw(struct rpmsg_channel *, u32, u32, void *, int, bool);
 
 /**
  * rpmsg_send() - send a message across to the remote processor
- * @rpdev: the rpmsg channel
+ * @ept: the rpmsg endpoint
  * @data: payload of message
  * @len: length of payload
  *
- * This function sends @data of length @len on the @rpdev channel.
- * The message will be sent to the remote processor which the @rpdev
- * channel belongs to, using @rpdev's source and destination addresses.
+ * This function sends @data of length @len on the @ept endpoint.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to, using @ept's address and its associated rpmsg
+ * device destination addresses.
  * In case there are no TX buffers available, the function will block until
  * one becomes available, or a timeout of 15 seconds elapses. When the latter
  * happens, -ERESTARTSYS is returned.
@@ -208,23 +209,24 @@ rpmsg_send_offchannel_raw(struct rpmsg_channel *, u32, u32, void *, int, bool);
  *
  * Returns 0 on success and an appropriate error value on failure.
  */
-static inline int rpmsg_send(struct rpmsg_channel *rpdev, void *data, int len)
+static inline int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
 {
-	u32 src = rpdev->src, dst = rpdev->dst;
+	struct rpmsg_channel *rpdev = ept->rpdev;
+	u32 src = ept->addr, dst = rpdev->dst;
 
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
 }
 
 /**
  * rpmsg_sendto() - send a message across to the remote processor, specify dst
- * @rpdev: the rpmsg channel
+ * @ept: the rpmsg endpoint
  * @data: payload of message
  * @len: length of payload
  * @dst: destination address
  *
  * This function sends @data of length @len to the remote @dst address.
- * The message will be sent to the remote processor which the @rpdev
- * channel belongs to, using @rpdev's source address.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to, using @ept's address as source.
  * In case there are no TX buffers available, the function will block until
  * one becomes available, or a timeout of 15 seconds elapses. When the latter
  * happens, -ERESTARTSYS is returned.
@@ -234,16 +236,17 @@ static inline int rpmsg_send(struct rpmsg_channel *rpdev, void *data, int len)
  * Returns 0 on success and an appropriate error value on failure.
  */
 static inline
-int rpmsg_sendto(struct rpmsg_channel *rpdev, void *data, int len, u32 dst)
+int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
 {
-	u32 src = rpdev->src;
+	struct rpmsg_channel *rpdev = ept->rpdev;
+	u32 src = ept->addr;
 
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
 }
 
 /**
  * rpmsg_send_offchannel() - send a message using explicit src/dst addresses
- * @rpdev: the rpmsg channel
+ * @ept: the rpmsg endpoint
  * @src: source address
  * @dst: destination address
  * @data: payload of message
@@ -251,8 +254,8 @@ int rpmsg_sendto(struct rpmsg_channel *rpdev, void *data, int len, u32 dst)
  *
  * This function sends @data of length @len to the remote @dst address,
  * and uses @src as the source address.
- * The message will be sent to the remote processor which the @rpdev
- * channel belongs to.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to.
  * In case there are no TX buffers available, the function will block until
  * one becomes available, or a timeout of 15 seconds elapses. When the latter
  * happens, -ERESTARTSYS is returned.
@@ -262,21 +265,24 @@ int rpmsg_sendto(struct rpmsg_channel *rpdev, void *data, int len, u32 dst)
  * Returns 0 on success and an appropriate error value on failure.
  */
 static inline
-int rpmsg_send_offchannel(struct rpmsg_channel *rpdev, u32 src, u32 dst,
+int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
 			  void *data, int len)
 {
+	struct rpmsg_channel *rpdev = ept->rpdev;
+
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
 }
 
 /**
  * rpmsg_send() - send a message across to the remote processor
- * @rpdev: the rpmsg channel
+ * @ept: the rpmsg endpoint
  * @data: payload of message
  * @len: length of payload
  *
- * This function sends @data of length @len on the @rpdev channel.
- * The message will be sent to the remote processor which the @rpdev
- * channel belongs to, using @rpdev's source and destination addresses.
+ * This function sends @data of length @len on the @ept endpoint.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to, using @ept's addres as source and its associated
+ * rpdev's address as destination.
  * In case there are no TX buffers available, the function will immediately
  * return -ENOMEM without waiting until one becomes available.
  *
@@ -285,23 +291,24 @@ int rpmsg_send_offchannel(struct rpmsg_channel *rpdev, u32 src, u32 dst,
  * Returns 0 on success and an appropriate error value on failure.
  */
 static inline
-int rpmsg_trysend(struct rpmsg_channel *rpdev, void *data, int len)
+int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
 {
-	u32 src = rpdev->src, dst = rpdev->dst;
+	struct rpmsg_channel *rpdev = ept->rpdev;
+	u32 src = ept->addr, dst = rpdev->dst;
 
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
 }
 
 /**
  * rpmsg_sendto() - send a message across to the remote processor, specify dst
- * @rpdev: the rpmsg channel
+ * @ept: the rpmsg endpoint
  * @data: payload of message
  * @len: length of payload
  * @dst: destination address
  *
  * This function sends @data of length @len to the remote @dst address.
- * The message will be sent to the remote processor which the @rpdev
- * channel belongs to, using @rpdev's source address.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to, using @ept's address as source.
  * In case there are no TX buffers available, the function will immediately
  * return -ENOMEM without waiting until one becomes available.
  *
@@ -310,16 +317,17 @@ int rpmsg_trysend(struct rpmsg_channel *rpdev, void *data, int len)
  * Returns 0 on success and an appropriate error value on failure.
  */
 static inline
-int rpmsg_trysendto(struct rpmsg_channel *rpdev, void *data, int len, u32 dst)
+int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
 {
-	u32 src = rpdev->src;
+	struct rpmsg_channel *rpdev = ept->rpdev;
+	u32 src = ept->addr;
 
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
 }
 
 /**
  * rpmsg_send_offchannel() - send a message using explicit src/dst addresses
- * @rpdev: the rpmsg channel
+ * @ept: the rpmsg endpoint
  * @src: source address
  * @dst: destination address
  * @data: payload of message
@@ -327,8 +335,8 @@ int rpmsg_trysendto(struct rpmsg_channel *rpdev, void *data, int len, u32 dst)
  *
  * This function sends @data of length @len to the remote @dst address,
  * and uses @src as the source address.
- * The message will be sent to the remote processor which the @rpdev
- * channel belongs to.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to.
  * In case there are no TX buffers available, the function will immediately
  * return -ENOMEM without waiting until one becomes available.
  *
@@ -337,9 +345,11 @@ int rpmsg_trysendto(struct rpmsg_channel *rpdev, void *data, int len, u32 dst)
  * Returns 0 on success and an appropriate error value on failure.
  */
 static inline
-int rpmsg_trysend_offchannel(struct rpmsg_channel *rpdev, u32 src, u32 dst,
+int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
 			     void *data, int len)
 {
+	struct rpmsg_channel *rpdev = ept->rpdev;
+
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
 }
 
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 03/14] rpmsg: rpmsg_send() operations takes rpmsg_endpoint
@ 2016-08-16  0:17   ` Bjorn Andersson
  0 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-16  0:17 UTC (permalink / raw)
  To: linux-arm-kernel

The rpmsg_send() operations has been taking a rpmsg_device, but this
forces users of secondary rpmsg_endpoints to use the rpmsg_sendto()
interface - by extracting source and destination from the given data
structures. If we instead pass the rpmsg_endpoint to these functions a
service can use rpmsg_sendto() to respond to messages, even on secondary
endpoints.

In addition this would allow us to support operations on multiple
channels in future backends that does not support off-channel
operations.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/rpmsg/virtio_rpmsg_bus.c |  4 +--
 include/linux/rpmsg.h            | 70 +++++++++++++++++++++++-----------------
 2 files changed, 42 insertions(+), 32 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index c4bd89ea7681..1b63f4b7c2bd 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -382,7 +382,7 @@ static int rpmsg_dev_probe(struct device *dev)
 		nsm.addr = rpdev->src;
 		nsm.flags = RPMSG_NS_CREATE;
 
-		err = rpmsg_sendto(rpdev, &nsm, sizeof(nsm), RPMSG_NS_ADDR);
+		err = rpmsg_sendto(rpdev->ept, &nsm, sizeof(nsm), RPMSG_NS_ADDR);
 		if (err)
 			dev_err(dev, "failed to announce service %d\n", err);
 	}
@@ -407,7 +407,7 @@ static int rpmsg_dev_remove(struct device *dev)
 		nsm.addr = rpdev->src;
 		nsm.flags = RPMSG_NS_DESTROY;
 
-		err = rpmsg_sendto(rpdev, &nsm, sizeof(nsm), RPMSG_NS_ADDR);
+		err = rpmsg_sendto(rpdev->ept, &nsm, sizeof(nsm), RPMSG_NS_ADDR);
 		if (err)
 			dev_err(dev, "failed to announce service %d\n", err);
 	}
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index 2b97c711a5e3..88e302c011e6 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -193,13 +193,14 @@ rpmsg_send_offchannel_raw(struct rpmsg_channel *, u32, u32, void *, int, bool);
 
 /**
  * rpmsg_send() - send a message across to the remote processor
- * @rpdev: the rpmsg channel
+ * @ept: the rpmsg endpoint
  * @data: payload of message
  * @len: length of payload
  *
- * This function sends @data of length @len on the @rpdev channel.
- * The message will be sent to the remote processor which the @rpdev
- * channel belongs to, using @rpdev's source and destination addresses.
+ * This function sends @data of length @len on the @ept endpoint.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to, using @ept's address and its associated rpmsg
+ * device destination addresses.
  * In case there are no TX buffers available, the function will block until
  * one becomes available, or a timeout of 15 seconds elapses. When the latter
  * happens, -ERESTARTSYS is returned.
@@ -208,23 +209,24 @@ rpmsg_send_offchannel_raw(struct rpmsg_channel *, u32, u32, void *, int, bool);
  *
  * Returns 0 on success and an appropriate error value on failure.
  */
-static inline int rpmsg_send(struct rpmsg_channel *rpdev, void *data, int len)
+static inline int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
 {
-	u32 src = rpdev->src, dst = rpdev->dst;
+	struct rpmsg_channel *rpdev = ept->rpdev;
+	u32 src = ept->addr, dst = rpdev->dst;
 
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
 }
 
 /**
  * rpmsg_sendto() - send a message across to the remote processor, specify dst
- * @rpdev: the rpmsg channel
+ * @ept: the rpmsg endpoint
  * @data: payload of message
  * @len: length of payload
  * @dst: destination address
  *
  * This function sends @data of length @len to the remote @dst address.
- * The message will be sent to the remote processor which the @rpdev
- * channel belongs to, using @rpdev's source address.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to, using @ept's address as source.
  * In case there are no TX buffers available, the function will block until
  * one becomes available, or a timeout of 15 seconds elapses. When the latter
  * happens, -ERESTARTSYS is returned.
@@ -234,16 +236,17 @@ static inline int rpmsg_send(struct rpmsg_channel *rpdev, void *data, int len)
  * Returns 0 on success and an appropriate error value on failure.
  */
 static inline
-int rpmsg_sendto(struct rpmsg_channel *rpdev, void *data, int len, u32 dst)
+int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
 {
-	u32 src = rpdev->src;
+	struct rpmsg_channel *rpdev = ept->rpdev;
+	u32 src = ept->addr;
 
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
 }
 
 /**
  * rpmsg_send_offchannel() - send a message using explicit src/dst addresses
- * @rpdev: the rpmsg channel
+ * @ept: the rpmsg endpoint
  * @src: source address
  * @dst: destination address
  * @data: payload of message
@@ -251,8 +254,8 @@ int rpmsg_sendto(struct rpmsg_channel *rpdev, void *data, int len, u32 dst)
  *
  * This function sends @data of length @len to the remote @dst address,
  * and uses @src as the source address.
- * The message will be sent to the remote processor which the @rpdev
- * channel belongs to.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to.
  * In case there are no TX buffers available, the function will block until
  * one becomes available, or a timeout of 15 seconds elapses. When the latter
  * happens, -ERESTARTSYS is returned.
@@ -262,21 +265,24 @@ int rpmsg_sendto(struct rpmsg_channel *rpdev, void *data, int len, u32 dst)
  * Returns 0 on success and an appropriate error value on failure.
  */
 static inline
-int rpmsg_send_offchannel(struct rpmsg_channel *rpdev, u32 src, u32 dst,
+int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
 			  void *data, int len)
 {
+	struct rpmsg_channel *rpdev = ept->rpdev;
+
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
 }
 
 /**
  * rpmsg_send() - send a message across to the remote processor
- * @rpdev: the rpmsg channel
+ * @ept: the rpmsg endpoint
  * @data: payload of message
  * @len: length of payload
  *
- * This function sends @data of length @len on the @rpdev channel.
- * The message will be sent to the remote processor which the @rpdev
- * channel belongs to, using @rpdev's source and destination addresses.
+ * This function sends @data of length @len on the @ept endpoint.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to, using @ept's addres as source and its associated
+ * rpdev's address as destination.
  * In case there are no TX buffers available, the function will immediately
  * return -ENOMEM without waiting until one becomes available.
  *
@@ -285,23 +291,24 @@ int rpmsg_send_offchannel(struct rpmsg_channel *rpdev, u32 src, u32 dst,
  * Returns 0 on success and an appropriate error value on failure.
  */
 static inline
-int rpmsg_trysend(struct rpmsg_channel *rpdev, void *data, int len)
+int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
 {
-	u32 src = rpdev->src, dst = rpdev->dst;
+	struct rpmsg_channel *rpdev = ept->rpdev;
+	u32 src = ept->addr, dst = rpdev->dst;
 
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
 }
 
 /**
  * rpmsg_sendto() - send a message across to the remote processor, specify dst
- * @rpdev: the rpmsg channel
+ * @ept: the rpmsg endpoint
  * @data: payload of message
  * @len: length of payload
  * @dst: destination address
  *
  * This function sends @data of length @len to the remote @dst address.
- * The message will be sent to the remote processor which the @rpdev
- * channel belongs to, using @rpdev's source address.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to, using @ept's address as source.
  * In case there are no TX buffers available, the function will immediately
  * return -ENOMEM without waiting until one becomes available.
  *
@@ -310,16 +317,17 @@ int rpmsg_trysend(struct rpmsg_channel *rpdev, void *data, int len)
  * Returns 0 on success and an appropriate error value on failure.
  */
 static inline
-int rpmsg_trysendto(struct rpmsg_channel *rpdev, void *data, int len, u32 dst)
+int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
 {
-	u32 src = rpdev->src;
+	struct rpmsg_channel *rpdev = ept->rpdev;
+	u32 src = ept->addr;
 
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
 }
 
 /**
  * rpmsg_send_offchannel() - send a message using explicit src/dst addresses
- * @rpdev: the rpmsg channel
+ * @ept: the rpmsg endpoint
  * @src: source address
  * @dst: destination address
  * @data: payload of message
@@ -327,8 +335,8 @@ int rpmsg_trysendto(struct rpmsg_channel *rpdev, void *data, int len, u32 dst)
  *
  * This function sends @data of length @len to the remote @dst address,
  * and uses @src as the source address.
- * The message will be sent to the remote processor which the @rpdev
- * channel belongs to.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to.
  * In case there are no TX buffers available, the function will immediately
  * return -ENOMEM without waiting until one becomes available.
  *
@@ -337,9 +345,11 @@ int rpmsg_trysendto(struct rpmsg_channel *rpdev, void *data, int len, u32 dst)
  * Returns 0 on success and an appropriate error value on failure.
  */
 static inline
-int rpmsg_trysend_offchannel(struct rpmsg_channel *rpdev, u32 src, u32 dst,
+int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
 			     void *data, int len)
 {
+	struct rpmsg_channel *rpdev = ept->rpdev;
+
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
 }
 
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 04/14] rpmsg: Internalize rpmsg_send() implementations
  2016-08-16  0:17 ` Bjorn Andersson
  (?)
@ 2016-08-16  0:17   ` Bjorn Andersson
  -1 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-16  0:17 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson
  Cc: linux-remoteproc, linux-arm-msm, linux-arm-kernel, linux-kernel

Move the rpmsg_send() implementations to virtio_rpmsg_bus.c in
preparation for upcoming changes making necessary data unavailable
outside the rpmsg implementation.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/rpmsg/virtio_rpmsg_bus.c | 169 ++++++++++++++++++++++++++++++++++++++-
 include/linux/rpmsg.h            | 166 ++------------------------------------
 2 files changed, 172 insertions(+), 163 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 1b63f4b7c2bd..f8fb9e065821 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -675,8 +675,9 @@ static void rpmsg_downref_sleepers(struct virtproc_info *vrp)
  *
  * Returns 0 on success and an appropriate error value on failure.
  */
-int rpmsg_send_offchannel_raw(struct rpmsg_channel *rpdev, u32 src, u32 dst,
-			      void *data, int len, bool wait)
+static int rpmsg_send_offchannel_raw(struct rpmsg_channel *rpdev,
+				     u32 src, u32 dst,
+				     void *data, int len, bool wait)
 {
 	struct virtproc_info *vrp = rpdev->vrp;
 	struct device *dev = &rpdev->dev;
@@ -770,7 +771,169 @@ out:
 	mutex_unlock(&vrp->tx_lock);
 	return err;
 }
-EXPORT_SYMBOL(rpmsg_send_offchannel_raw);
+
+/**
+ * rpmsg_send() - send a message across to the remote processor
+ * @ept: the rpmsg endpoint
+ * @data: payload of message
+ * @len: length of payload
+ *
+ * This function sends @data of length @len on the @ept endpoint.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to, using @ept's address and its associated rpmsg
+ * device destination addresses.
+ * In case there are no TX buffers available, the function will block until
+ * one becomes available, or a timeout of 15 seconds elapses. When the latter
+ * happens, -ERESTARTSYS is returned.
+ *
+ * Can only be called from process context (for now).
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
+{
+	struct rpmsg_channel *rpdev = ept->rpdev;
+	u32 src = ept->addr, dst = rpdev->dst;
+
+	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
+}
+EXPORT_SYMBOL(rpmsg_send);
+
+/**
+ * rpmsg_sendto() - send a message across to the remote processor, specify dst
+ * @ept: the rpmsg endpoint
+ * @data: payload of message
+ * @len: length of payload
+ * @dst: destination address
+ *
+ * This function sends @data of length @len to the remote @dst address.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to, using @ept's address as source.
+ * In case there are no TX buffers available, the function will block until
+ * one becomes available, or a timeout of 15 seconds elapses. When the latter
+ * happens, -ERESTARTSYS is returned.
+ *
+ * Can only be called from process context (for now).
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
+{
+	struct rpmsg_channel *rpdev = ept->rpdev;
+	u32 src = ept->addr;
+
+	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
+}
+EXPORT_SYMBOL(rpmsg_sendto);
+
+/**
+ * rpmsg_send_offchannel() - send a message using explicit src/dst addresses
+ * @ept: the rpmsg endpoint
+ * @src: source address
+ * @dst: destination address
+ * @data: payload of message
+ * @len: length of payload
+ *
+ * This function sends @data of length @len to the remote @dst address,
+ * and uses @src as the source address.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to.
+ * In case there are no TX buffers available, the function will block until
+ * one becomes available, or a timeout of 15 seconds elapses. When the latter
+ * happens, -ERESTARTSYS is returned.
+ *
+ * Can only be called from process context (for now).
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
+			  void *data, int len)
+{
+	struct rpmsg_channel *rpdev = ept->rpdev;
+
+	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
+}
+EXPORT_SYMBOL(rpmsg_send_offchannel);
+
+/**
+ * rpmsg_send() - send a message across to the remote processor
+ * @ept: the rpmsg endpoint
+ * @data: payload of message
+ * @len: length of payload
+ *
+ * This function sends @data of length @len on the @ept endpoint.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to, using @ept's addres as source and its associated
+ * rpdev's address as destination.
+ * In case there are no TX buffers available, the function will immediately
+ * return -ENOMEM without waiting until one becomes available.
+ *
+ * Can only be called from process context (for now).
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
+{
+	struct rpmsg_channel *rpdev = ept->rpdev;
+	u32 src = ept->addr, dst = rpdev->dst;
+
+	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
+}
+EXPORT_SYMBOL(rpmsg_trysend);
+
+/**
+ * rpmsg_sendto() - send a message across to the remote processor, specify dst
+ * @ept: the rpmsg endpoint
+ * @data: payload of message
+ * @len: length of payload
+ * @dst: destination address
+ *
+ * This function sends @data of length @len to the remote @dst address.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to, using @ept's address as source.
+ * In case there are no TX buffers available, the function will immediately
+ * return -ENOMEM without waiting until one becomes available.
+ *
+ * Can only be called from process context (for now).
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
+{
+	struct rpmsg_channel *rpdev = ept->rpdev;
+	u32 src = ept->addr;
+
+	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
+}
+EXPORT_SYMBOL(rpmsg_trysendto);
+
+/**
+ * rpmsg_send_offchannel() - send a message using explicit src/dst addresses
+ * @ept: the rpmsg endpoint
+ * @src: source address
+ * @dst: destination address
+ * @data: payload of message
+ * @len: length of payload
+ *
+ * This function sends @data of length @len to the remote @dst address,
+ * and uses @src as the source address.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to.
+ * In case there are no TX buffers available, the function will immediately
+ * return -ENOMEM without waiting until one becomes available.
+ *
+ * Can only be called from process context (for now).
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
+			     void *data, int len)
+{
+	struct rpmsg_channel *rpdev = ept->rpdev;
+
+	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
+}
+EXPORT_SYMBOL(rpmsg_trysend_offchannel);
 
 static int rpmsg_recv_single(struct virtproc_info *vrp, struct device *dev,
 			     struct rpmsg_hdr *msg, unsigned int len)
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index 88e302c011e6..554dc352d7e0 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -172,8 +172,6 @@ void unregister_rpmsg_driver(struct rpmsg_driver *drv);
 void rpmsg_destroy_ept(struct rpmsg_endpoint *);
 struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_channel *,
 					rpmsg_rx_cb_t cb, void *priv, u32 addr);
-int
-rpmsg_send_offchannel_raw(struct rpmsg_channel *, u32, u32, void *, int, bool);
 
 /* use a macro to avoid include chaining to get THIS_MODULE */
 #define register_rpmsg_driver(drv) \
@@ -191,166 +189,14 @@ rpmsg_send_offchannel_raw(struct rpmsg_channel *, u32, u32, void *, int, bool);
 	module_driver(__rpmsg_driver, register_rpmsg_driver, \
 			unregister_rpmsg_driver)
 
-/**
- * rpmsg_send() - send a message across to the remote processor
- * @ept: the rpmsg endpoint
- * @data: payload of message
- * @len: length of payload
- *
- * This function sends @data of length @len on the @ept endpoint.
- * The message will be sent to the remote processor which the @ept
- * endpoint belongs to, using @ept's address and its associated rpmsg
- * device destination addresses.
- * In case there are no TX buffers available, the function will block until
- * one becomes available, or a timeout of 15 seconds elapses. When the latter
- * happens, -ERESTARTSYS is returned.
- *
- * Can only be called from process context (for now).
- *
- * Returns 0 on success and an appropriate error value on failure.
- */
-static inline int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
-{
-	struct rpmsg_channel *rpdev = ept->rpdev;
-	u32 src = ept->addr, dst = rpdev->dst;
-
-	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
-}
-
-/**
- * rpmsg_sendto() - send a message across to the remote processor, specify dst
- * @ept: the rpmsg endpoint
- * @data: payload of message
- * @len: length of payload
- * @dst: destination address
- *
- * This function sends @data of length @len to the remote @dst address.
- * The message will be sent to the remote processor which the @ept
- * endpoint belongs to, using @ept's address as source.
- * In case there are no TX buffers available, the function will block until
- * one becomes available, or a timeout of 15 seconds elapses. When the latter
- * happens, -ERESTARTSYS is returned.
- *
- * Can only be called from process context (for now).
- *
- * Returns 0 on success and an appropriate error value on failure.
- */
-static inline
-int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
-{
-	struct rpmsg_channel *rpdev = ept->rpdev;
-	u32 src = ept->addr;
-
-	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
-}
-
-/**
- * rpmsg_send_offchannel() - send a message using explicit src/dst addresses
- * @ept: the rpmsg endpoint
- * @src: source address
- * @dst: destination address
- * @data: payload of message
- * @len: length of payload
- *
- * This function sends @data of length @len to the remote @dst address,
- * and uses @src as the source address.
- * The message will be sent to the remote processor which the @ept
- * endpoint belongs to.
- * In case there are no TX buffers available, the function will block until
- * one becomes available, or a timeout of 15 seconds elapses. When the latter
- * happens, -ERESTARTSYS is returned.
- *
- * Can only be called from process context (for now).
- *
- * Returns 0 on success and an appropriate error value on failure.
- */
-static inline
+int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len);
+int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst);
 int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
-			  void *data, int len)
-{
-	struct rpmsg_channel *rpdev = ept->rpdev;
-
-	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
-}
+			  void *data, int len);
 
-/**
- * rpmsg_send() - send a message across to the remote processor
- * @ept: the rpmsg endpoint
- * @data: payload of message
- * @len: length of payload
- *
- * This function sends @data of length @len on the @ept endpoint.
- * The message will be sent to the remote processor which the @ept
- * endpoint belongs to, using @ept's addres as source and its associated
- * rpdev's address as destination.
- * In case there are no TX buffers available, the function will immediately
- * return -ENOMEM without waiting until one becomes available.
- *
- * Can only be called from process context (for now).
- *
- * Returns 0 on success and an appropriate error value on failure.
- */
-static inline
-int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
-{
-	struct rpmsg_channel *rpdev = ept->rpdev;
-	u32 src = ept->addr, dst = rpdev->dst;
-
-	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
-}
-
-/**
- * rpmsg_sendto() - send a message across to the remote processor, specify dst
- * @ept: the rpmsg endpoint
- * @data: payload of message
- * @len: length of payload
- * @dst: destination address
- *
- * This function sends @data of length @len to the remote @dst address.
- * The message will be sent to the remote processor which the @ept
- * endpoint belongs to, using @ept's address as source.
- * In case there are no TX buffers available, the function will immediately
- * return -ENOMEM without waiting until one becomes available.
- *
- * Can only be called from process context (for now).
- *
- * Returns 0 on success and an appropriate error value on failure.
- */
-static inline
-int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
-{
-	struct rpmsg_channel *rpdev = ept->rpdev;
-	u32 src = ept->addr;
-
-	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
-}
-
-/**
- * rpmsg_send_offchannel() - send a message using explicit src/dst addresses
- * @ept: the rpmsg endpoint
- * @src: source address
- * @dst: destination address
- * @data: payload of message
- * @len: length of payload
- *
- * This function sends @data of length @len to the remote @dst address,
- * and uses @src as the source address.
- * The message will be sent to the remote processor which the @ept
- * endpoint belongs to.
- * In case there are no TX buffers available, the function will immediately
- * return -ENOMEM without waiting until one becomes available.
- *
- * Can only be called from process context (for now).
- *
- * Returns 0 on success and an appropriate error value on failure.
- */
-static inline
+int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len);
+int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst);
 int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
-			     void *data, int len)
-{
-	struct rpmsg_channel *rpdev = ept->rpdev;
-
-	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
-}
+			     void *data, int len);
 
 #endif /* _LINUX_RPMSG_H */
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 04/14] rpmsg: Internalize rpmsg_send() implementations
@ 2016-08-16  0:17   ` Bjorn Andersson
  0 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-16  0:17 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson
  Cc: linux-arm-msm, linux-remoteproc, linux-kernel, linux-arm-kernel

Move the rpmsg_send() implementations to virtio_rpmsg_bus.c in
preparation for upcoming changes making necessary data unavailable
outside the rpmsg implementation.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/rpmsg/virtio_rpmsg_bus.c | 169 ++++++++++++++++++++++++++++++++++++++-
 include/linux/rpmsg.h            | 166 ++------------------------------------
 2 files changed, 172 insertions(+), 163 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 1b63f4b7c2bd..f8fb9e065821 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -675,8 +675,9 @@ static void rpmsg_downref_sleepers(struct virtproc_info *vrp)
  *
  * Returns 0 on success and an appropriate error value on failure.
  */
-int rpmsg_send_offchannel_raw(struct rpmsg_channel *rpdev, u32 src, u32 dst,
-			      void *data, int len, bool wait)
+static int rpmsg_send_offchannel_raw(struct rpmsg_channel *rpdev,
+				     u32 src, u32 dst,
+				     void *data, int len, bool wait)
 {
 	struct virtproc_info *vrp = rpdev->vrp;
 	struct device *dev = &rpdev->dev;
@@ -770,7 +771,169 @@ out:
 	mutex_unlock(&vrp->tx_lock);
 	return err;
 }
-EXPORT_SYMBOL(rpmsg_send_offchannel_raw);
+
+/**
+ * rpmsg_send() - send a message across to the remote processor
+ * @ept: the rpmsg endpoint
+ * @data: payload of message
+ * @len: length of payload
+ *
+ * This function sends @data of length @len on the @ept endpoint.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to, using @ept's address and its associated rpmsg
+ * device destination addresses.
+ * In case there are no TX buffers available, the function will block until
+ * one becomes available, or a timeout of 15 seconds elapses. When the latter
+ * happens, -ERESTARTSYS is returned.
+ *
+ * Can only be called from process context (for now).
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
+{
+	struct rpmsg_channel *rpdev = ept->rpdev;
+	u32 src = ept->addr, dst = rpdev->dst;
+
+	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
+}
+EXPORT_SYMBOL(rpmsg_send);
+
+/**
+ * rpmsg_sendto() - send a message across to the remote processor, specify dst
+ * @ept: the rpmsg endpoint
+ * @data: payload of message
+ * @len: length of payload
+ * @dst: destination address
+ *
+ * This function sends @data of length @len to the remote @dst address.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to, using @ept's address as source.
+ * In case there are no TX buffers available, the function will block until
+ * one becomes available, or a timeout of 15 seconds elapses. When the latter
+ * happens, -ERESTARTSYS is returned.
+ *
+ * Can only be called from process context (for now).
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
+{
+	struct rpmsg_channel *rpdev = ept->rpdev;
+	u32 src = ept->addr;
+
+	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
+}
+EXPORT_SYMBOL(rpmsg_sendto);
+
+/**
+ * rpmsg_send_offchannel() - send a message using explicit src/dst addresses
+ * @ept: the rpmsg endpoint
+ * @src: source address
+ * @dst: destination address
+ * @data: payload of message
+ * @len: length of payload
+ *
+ * This function sends @data of length @len to the remote @dst address,
+ * and uses @src as the source address.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to.
+ * In case there are no TX buffers available, the function will block until
+ * one becomes available, or a timeout of 15 seconds elapses. When the latter
+ * happens, -ERESTARTSYS is returned.
+ *
+ * Can only be called from process context (for now).
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
+			  void *data, int len)
+{
+	struct rpmsg_channel *rpdev = ept->rpdev;
+
+	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
+}
+EXPORT_SYMBOL(rpmsg_send_offchannel);
+
+/**
+ * rpmsg_send() - send a message across to the remote processor
+ * @ept: the rpmsg endpoint
+ * @data: payload of message
+ * @len: length of payload
+ *
+ * This function sends @data of length @len on the @ept endpoint.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to, using @ept's addres as source and its associated
+ * rpdev's address as destination.
+ * In case there are no TX buffers available, the function will immediately
+ * return -ENOMEM without waiting until one becomes available.
+ *
+ * Can only be called from process context (for now).
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
+{
+	struct rpmsg_channel *rpdev = ept->rpdev;
+	u32 src = ept->addr, dst = rpdev->dst;
+
+	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
+}
+EXPORT_SYMBOL(rpmsg_trysend);
+
+/**
+ * rpmsg_sendto() - send a message across to the remote processor, specify dst
+ * @ept: the rpmsg endpoint
+ * @data: payload of message
+ * @len: length of payload
+ * @dst: destination address
+ *
+ * This function sends @data of length @len to the remote @dst address.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to, using @ept's address as source.
+ * In case there are no TX buffers available, the function will immediately
+ * return -ENOMEM without waiting until one becomes available.
+ *
+ * Can only be called from process context (for now).
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
+{
+	struct rpmsg_channel *rpdev = ept->rpdev;
+	u32 src = ept->addr;
+
+	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
+}
+EXPORT_SYMBOL(rpmsg_trysendto);
+
+/**
+ * rpmsg_send_offchannel() - send a message using explicit src/dst addresses
+ * @ept: the rpmsg endpoint
+ * @src: source address
+ * @dst: destination address
+ * @data: payload of message
+ * @len: length of payload
+ *
+ * This function sends @data of length @len to the remote @dst address,
+ * and uses @src as the source address.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to.
+ * In case there are no TX buffers available, the function will immediately
+ * return -ENOMEM without waiting until one becomes available.
+ *
+ * Can only be called from process context (for now).
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
+			     void *data, int len)
+{
+	struct rpmsg_channel *rpdev = ept->rpdev;
+
+	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
+}
+EXPORT_SYMBOL(rpmsg_trysend_offchannel);
 
 static int rpmsg_recv_single(struct virtproc_info *vrp, struct device *dev,
 			     struct rpmsg_hdr *msg, unsigned int len)
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index 88e302c011e6..554dc352d7e0 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -172,8 +172,6 @@ void unregister_rpmsg_driver(struct rpmsg_driver *drv);
 void rpmsg_destroy_ept(struct rpmsg_endpoint *);
 struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_channel *,
 					rpmsg_rx_cb_t cb, void *priv, u32 addr);
-int
-rpmsg_send_offchannel_raw(struct rpmsg_channel *, u32, u32, void *, int, bool);
 
 /* use a macro to avoid include chaining to get THIS_MODULE */
 #define register_rpmsg_driver(drv) \
@@ -191,166 +189,14 @@ rpmsg_send_offchannel_raw(struct rpmsg_channel *, u32, u32, void *, int, bool);
 	module_driver(__rpmsg_driver, register_rpmsg_driver, \
 			unregister_rpmsg_driver)
 
-/**
- * rpmsg_send() - send a message across to the remote processor
- * @ept: the rpmsg endpoint
- * @data: payload of message
- * @len: length of payload
- *
- * This function sends @data of length @len on the @ept endpoint.
- * The message will be sent to the remote processor which the @ept
- * endpoint belongs to, using @ept's address and its associated rpmsg
- * device destination addresses.
- * In case there are no TX buffers available, the function will block until
- * one becomes available, or a timeout of 15 seconds elapses. When the latter
- * happens, -ERESTARTSYS is returned.
- *
- * Can only be called from process context (for now).
- *
- * Returns 0 on success and an appropriate error value on failure.
- */
-static inline int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
-{
-	struct rpmsg_channel *rpdev = ept->rpdev;
-	u32 src = ept->addr, dst = rpdev->dst;
-
-	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
-}
-
-/**
- * rpmsg_sendto() - send a message across to the remote processor, specify dst
- * @ept: the rpmsg endpoint
- * @data: payload of message
- * @len: length of payload
- * @dst: destination address
- *
- * This function sends @data of length @len to the remote @dst address.
- * The message will be sent to the remote processor which the @ept
- * endpoint belongs to, using @ept's address as source.
- * In case there are no TX buffers available, the function will block until
- * one becomes available, or a timeout of 15 seconds elapses. When the latter
- * happens, -ERESTARTSYS is returned.
- *
- * Can only be called from process context (for now).
- *
- * Returns 0 on success and an appropriate error value on failure.
- */
-static inline
-int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
-{
-	struct rpmsg_channel *rpdev = ept->rpdev;
-	u32 src = ept->addr;
-
-	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
-}
-
-/**
- * rpmsg_send_offchannel() - send a message using explicit src/dst addresses
- * @ept: the rpmsg endpoint
- * @src: source address
- * @dst: destination address
- * @data: payload of message
- * @len: length of payload
- *
- * This function sends @data of length @len to the remote @dst address,
- * and uses @src as the source address.
- * The message will be sent to the remote processor which the @ept
- * endpoint belongs to.
- * In case there are no TX buffers available, the function will block until
- * one becomes available, or a timeout of 15 seconds elapses. When the latter
- * happens, -ERESTARTSYS is returned.
- *
- * Can only be called from process context (for now).
- *
- * Returns 0 on success and an appropriate error value on failure.
- */
-static inline
+int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len);
+int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst);
 int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
-			  void *data, int len)
-{
-	struct rpmsg_channel *rpdev = ept->rpdev;
-
-	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
-}
+			  void *data, int len);
 
-/**
- * rpmsg_send() - send a message across to the remote processor
- * @ept: the rpmsg endpoint
- * @data: payload of message
- * @len: length of payload
- *
- * This function sends @data of length @len on the @ept endpoint.
- * The message will be sent to the remote processor which the @ept
- * endpoint belongs to, using @ept's addres as source and its associated
- * rpdev's address as destination.
- * In case there are no TX buffers available, the function will immediately
- * return -ENOMEM without waiting until one becomes available.
- *
- * Can only be called from process context (for now).
- *
- * Returns 0 on success and an appropriate error value on failure.
- */
-static inline
-int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
-{
-	struct rpmsg_channel *rpdev = ept->rpdev;
-	u32 src = ept->addr, dst = rpdev->dst;
-
-	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
-}
-
-/**
- * rpmsg_sendto() - send a message across to the remote processor, specify dst
- * @ept: the rpmsg endpoint
- * @data: payload of message
- * @len: length of payload
- * @dst: destination address
- *
- * This function sends @data of length @len to the remote @dst address.
- * The message will be sent to the remote processor which the @ept
- * endpoint belongs to, using @ept's address as source.
- * In case there are no TX buffers available, the function will immediately
- * return -ENOMEM without waiting until one becomes available.
- *
- * Can only be called from process context (for now).
- *
- * Returns 0 on success and an appropriate error value on failure.
- */
-static inline
-int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
-{
-	struct rpmsg_channel *rpdev = ept->rpdev;
-	u32 src = ept->addr;
-
-	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
-}
-
-/**
- * rpmsg_send_offchannel() - send a message using explicit src/dst addresses
- * @ept: the rpmsg endpoint
- * @src: source address
- * @dst: destination address
- * @data: payload of message
- * @len: length of payload
- *
- * This function sends @data of length @len to the remote @dst address,
- * and uses @src as the source address.
- * The message will be sent to the remote processor which the @ept
- * endpoint belongs to.
- * In case there are no TX buffers available, the function will immediately
- * return -ENOMEM without waiting until one becomes available.
- *
- * Can only be called from process context (for now).
- *
- * Returns 0 on success and an appropriate error value on failure.
- */
-static inline
+int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len);
+int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst);
 int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
-			     void *data, int len)
-{
-	struct rpmsg_channel *rpdev = ept->rpdev;
-
-	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
-}
+			     void *data, int len);
 
 #endif /* _LINUX_RPMSG_H */
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 04/14] rpmsg: Internalize rpmsg_send() implementations
@ 2016-08-16  0:17   ` Bjorn Andersson
  0 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-16  0:17 UTC (permalink / raw)
  To: linux-arm-kernel

Move the rpmsg_send() implementations to virtio_rpmsg_bus.c in
preparation for upcoming changes making necessary data unavailable
outside the rpmsg implementation.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/rpmsg/virtio_rpmsg_bus.c | 169 ++++++++++++++++++++++++++++++++++++++-
 include/linux/rpmsg.h            | 166 ++------------------------------------
 2 files changed, 172 insertions(+), 163 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 1b63f4b7c2bd..f8fb9e065821 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -675,8 +675,9 @@ static void rpmsg_downref_sleepers(struct virtproc_info *vrp)
  *
  * Returns 0 on success and an appropriate error value on failure.
  */
-int rpmsg_send_offchannel_raw(struct rpmsg_channel *rpdev, u32 src, u32 dst,
-			      void *data, int len, bool wait)
+static int rpmsg_send_offchannel_raw(struct rpmsg_channel *rpdev,
+				     u32 src, u32 dst,
+				     void *data, int len, bool wait)
 {
 	struct virtproc_info *vrp = rpdev->vrp;
 	struct device *dev = &rpdev->dev;
@@ -770,7 +771,169 @@ out:
 	mutex_unlock(&vrp->tx_lock);
 	return err;
 }
-EXPORT_SYMBOL(rpmsg_send_offchannel_raw);
+
+/**
+ * rpmsg_send() - send a message across to the remote processor
+ * @ept: the rpmsg endpoint
+ * @data: payload of message
+ * @len: length of payload
+ *
+ * This function sends @data of length @len on the @ept endpoint.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to, using @ept's address and its associated rpmsg
+ * device destination addresses.
+ * In case there are no TX buffers available, the function will block until
+ * one becomes available, or a timeout of 15 seconds elapses. When the latter
+ * happens, -ERESTARTSYS is returned.
+ *
+ * Can only be called from process context (for now).
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
+{
+	struct rpmsg_channel *rpdev = ept->rpdev;
+	u32 src = ept->addr, dst = rpdev->dst;
+
+	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
+}
+EXPORT_SYMBOL(rpmsg_send);
+
+/**
+ * rpmsg_sendto() - send a message across to the remote processor, specify dst
+ * @ept: the rpmsg endpoint
+ * @data: payload of message
+ * @len: length of payload
+ * @dst: destination address
+ *
+ * This function sends @data of length @len to the remote @dst address.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to, using @ept's address as source.
+ * In case there are no TX buffers available, the function will block until
+ * one becomes available, or a timeout of 15 seconds elapses. When the latter
+ * happens, -ERESTARTSYS is returned.
+ *
+ * Can only be called from process context (for now).
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
+{
+	struct rpmsg_channel *rpdev = ept->rpdev;
+	u32 src = ept->addr;
+
+	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
+}
+EXPORT_SYMBOL(rpmsg_sendto);
+
+/**
+ * rpmsg_send_offchannel() - send a message using explicit src/dst addresses
+ * @ept: the rpmsg endpoint
+ * @src: source address
+ * @dst: destination address
+ * @data: payload of message
+ * @len: length of payload
+ *
+ * This function sends @data of length @len to the remote @dst address,
+ * and uses @src as the source address.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to.
+ * In case there are no TX buffers available, the function will block until
+ * one becomes available, or a timeout of 15 seconds elapses. When the latter
+ * happens, -ERESTARTSYS is returned.
+ *
+ * Can only be called from process context (for now).
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
+			  void *data, int len)
+{
+	struct rpmsg_channel *rpdev = ept->rpdev;
+
+	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
+}
+EXPORT_SYMBOL(rpmsg_send_offchannel);
+
+/**
+ * rpmsg_send() - send a message across to the remote processor
+ * @ept: the rpmsg endpoint
+ * @data: payload of message
+ * @len: length of payload
+ *
+ * This function sends @data of length @len on the @ept endpoint.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to, using @ept's addres as source and its associated
+ * rpdev's address as destination.
+ * In case there are no TX buffers available, the function will immediately
+ * return -ENOMEM without waiting until one becomes available.
+ *
+ * Can only be called from process context (for now).
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
+{
+	struct rpmsg_channel *rpdev = ept->rpdev;
+	u32 src = ept->addr, dst = rpdev->dst;
+
+	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
+}
+EXPORT_SYMBOL(rpmsg_trysend);
+
+/**
+ * rpmsg_sendto() - send a message across to the remote processor, specify dst
+ * @ept: the rpmsg endpoint
+ * @data: payload of message
+ * @len: length of payload
+ * @dst: destination address
+ *
+ * This function sends @data of length @len to the remote @dst address.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to, using @ept's address as source.
+ * In case there are no TX buffers available, the function will immediately
+ * return -ENOMEM without waiting until one becomes available.
+ *
+ * Can only be called from process context (for now).
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
+{
+	struct rpmsg_channel *rpdev = ept->rpdev;
+	u32 src = ept->addr;
+
+	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
+}
+EXPORT_SYMBOL(rpmsg_trysendto);
+
+/**
+ * rpmsg_send_offchannel() - send a message using explicit src/dst addresses
+ * @ept: the rpmsg endpoint
+ * @src: source address
+ * @dst: destination address
+ * @data: payload of message
+ * @len: length of payload
+ *
+ * This function sends @data of length @len to the remote @dst address,
+ * and uses @src as the source address.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to.
+ * In case there are no TX buffers available, the function will immediately
+ * return -ENOMEM without waiting until one becomes available.
+ *
+ * Can only be called from process context (for now).
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
+			     void *data, int len)
+{
+	struct rpmsg_channel *rpdev = ept->rpdev;
+
+	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
+}
+EXPORT_SYMBOL(rpmsg_trysend_offchannel);
 
 static int rpmsg_recv_single(struct virtproc_info *vrp, struct device *dev,
 			     struct rpmsg_hdr *msg, unsigned int len)
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index 88e302c011e6..554dc352d7e0 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -172,8 +172,6 @@ void unregister_rpmsg_driver(struct rpmsg_driver *drv);
 void rpmsg_destroy_ept(struct rpmsg_endpoint *);
 struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_channel *,
 					rpmsg_rx_cb_t cb, void *priv, u32 addr);
-int
-rpmsg_send_offchannel_raw(struct rpmsg_channel *, u32, u32, void *, int, bool);
 
 /* use a macro to avoid include chaining to get THIS_MODULE */
 #define register_rpmsg_driver(drv) \
@@ -191,166 +189,14 @@ rpmsg_send_offchannel_raw(struct rpmsg_channel *, u32, u32, void *, int, bool);
 	module_driver(__rpmsg_driver, register_rpmsg_driver, \
 			unregister_rpmsg_driver)
 
-/**
- * rpmsg_send() - send a message across to the remote processor
- * @ept: the rpmsg endpoint
- * @data: payload of message
- * @len: length of payload
- *
- * This function sends @data of length @len on the @ept endpoint.
- * The message will be sent to the remote processor which the @ept
- * endpoint belongs to, using @ept's address and its associated rpmsg
- * device destination addresses.
- * In case there are no TX buffers available, the function will block until
- * one becomes available, or a timeout of 15 seconds elapses. When the latter
- * happens, -ERESTARTSYS is returned.
- *
- * Can only be called from process context (for now).
- *
- * Returns 0 on success and an appropriate error value on failure.
- */
-static inline int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
-{
-	struct rpmsg_channel *rpdev = ept->rpdev;
-	u32 src = ept->addr, dst = rpdev->dst;
-
-	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
-}
-
-/**
- * rpmsg_sendto() - send a message across to the remote processor, specify dst
- * @ept: the rpmsg endpoint
- * @data: payload of message
- * @len: length of payload
- * @dst: destination address
- *
- * This function sends @data of length @len to the remote @dst address.
- * The message will be sent to the remote processor which the @ept
- * endpoint belongs to, using @ept's address as source.
- * In case there are no TX buffers available, the function will block until
- * one becomes available, or a timeout of 15 seconds elapses. When the latter
- * happens, -ERESTARTSYS is returned.
- *
- * Can only be called from process context (for now).
- *
- * Returns 0 on success and an appropriate error value on failure.
- */
-static inline
-int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
-{
-	struct rpmsg_channel *rpdev = ept->rpdev;
-	u32 src = ept->addr;
-
-	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
-}
-
-/**
- * rpmsg_send_offchannel() - send a message using explicit src/dst addresses
- * @ept: the rpmsg endpoint
- * @src: source address
- * @dst: destination address
- * @data: payload of message
- * @len: length of payload
- *
- * This function sends @data of length @len to the remote @dst address,
- * and uses @src as the source address.
- * The message will be sent to the remote processor which the @ept
- * endpoint belongs to.
- * In case there are no TX buffers available, the function will block until
- * one becomes available, or a timeout of 15 seconds elapses. When the latter
- * happens, -ERESTARTSYS is returned.
- *
- * Can only be called from process context (for now).
- *
- * Returns 0 on success and an appropriate error value on failure.
- */
-static inline
+int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len);
+int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst);
 int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
-			  void *data, int len)
-{
-	struct rpmsg_channel *rpdev = ept->rpdev;
-
-	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
-}
+			  void *data, int len);
 
-/**
- * rpmsg_send() - send a message across to the remote processor
- * @ept: the rpmsg endpoint
- * @data: payload of message
- * @len: length of payload
- *
- * This function sends @data of length @len on the @ept endpoint.
- * The message will be sent to the remote processor which the @ept
- * endpoint belongs to, using @ept's addres as source and its associated
- * rpdev's address as destination.
- * In case there are no TX buffers available, the function will immediately
- * return -ENOMEM without waiting until one becomes available.
- *
- * Can only be called from process context (for now).
- *
- * Returns 0 on success and an appropriate error value on failure.
- */
-static inline
-int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
-{
-	struct rpmsg_channel *rpdev = ept->rpdev;
-	u32 src = ept->addr, dst = rpdev->dst;
-
-	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
-}
-
-/**
- * rpmsg_sendto() - send a message across to the remote processor, specify dst
- * @ept: the rpmsg endpoint
- * @data: payload of message
- * @len: length of payload
- * @dst: destination address
- *
- * This function sends @data of length @len to the remote @dst address.
- * The message will be sent to the remote processor which the @ept
- * endpoint belongs to, using @ept's address as source.
- * In case there are no TX buffers available, the function will immediately
- * return -ENOMEM without waiting until one becomes available.
- *
- * Can only be called from process context (for now).
- *
- * Returns 0 on success and an appropriate error value on failure.
- */
-static inline
-int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
-{
-	struct rpmsg_channel *rpdev = ept->rpdev;
-	u32 src = ept->addr;
-
-	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
-}
-
-/**
- * rpmsg_send_offchannel() - send a message using explicit src/dst addresses
- * @ept: the rpmsg endpoint
- * @src: source address
- * @dst: destination address
- * @data: payload of message
- * @len: length of payload
- *
- * This function sends @data of length @len to the remote @dst address,
- * and uses @src as the source address.
- * The message will be sent to the remote processor which the @ept
- * endpoint belongs to.
- * In case there are no TX buffers available, the function will immediately
- * return -ENOMEM without waiting until one becomes available.
- *
- * Can only be called from process context (for now).
- *
- * Returns 0 on success and an appropriate error value on failure.
- */
-static inline
+int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len);
+int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst);
 int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
-			     void *data, int len)
-{
-	struct rpmsg_channel *rpdev = ept->rpdev;
-
-	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
-}
+			     void *data, int len);
 
 #endif /* _LINUX_RPMSG_H */
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 05/14] rpmsg: Unify rpmsg device vs channel naming
  2016-08-16  0:17 ` Bjorn Andersson
@ 2016-08-16  0:17   ` Bjorn Andersson
  -1 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-16  0:17 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson
  Cc: linux-remoteproc, linux-arm-msm, linux-arm-kernel, linux-kernel

The rpmsg device representing struct is called rpmsg_channel and the
variable name used throughout is rpdev, unify these as "rpmsg device" so
that we can use the identifier "channel" for the internal object in the
future.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/rpmsg/virtio_rpmsg_bus.c | 54 ++++++++++++++++++++--------------------
 include/linux/rpmsg.h            | 18 ++++++++------
 2 files changed, 37 insertions(+), 35 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index f8fb9e065821..a9f8cc8d968b 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -85,7 +85,7 @@ struct rpmsg_channel_info {
 	u32 dst;
 };
 
-#define to_rpmsg_channel(d) container_of(d, struct rpmsg_channel, dev)
+#define to_rpmsg_device(d) container_of(d, struct rpmsg_device, dev)
 #define to_rpmsg_driver(d) container_of(d, struct rpmsg_driver, drv)
 
 /*
@@ -125,7 +125,7 @@ static ssize_t								\
 field##_show(struct device *dev,					\
 			struct device_attribute *attr, char *buf)	\
 {									\
-	struct rpmsg_channel *rpdev = to_rpmsg_channel(dev);		\
+	struct rpmsg_device *rpdev = to_rpmsg_device(dev);		\
 									\
 	return sprintf(buf, format_string, rpdev->path);		\
 }
@@ -139,7 +139,7 @@ rpmsg_show_attr(announce, announce ? "true" : "false", "%s\n");
 static ssize_t modalias_show(struct device *dev,
 			     struct device_attribute *attr, char *buf)
 {
-	struct rpmsg_channel *rpdev = to_rpmsg_channel(dev);
+	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
 
 	return sprintf(buf, RPMSG_DEVICE_MODALIAS_FMT "\n", rpdev->id.name);
 }
@@ -154,7 +154,7 @@ static struct device_attribute rpmsg_dev_attrs[] = {
 };
 
 /* rpmsg devices and drivers are matched using the service name */
-static inline int rpmsg_id_match(const struct rpmsg_channel *rpdev,
+static inline int rpmsg_id_match(const struct rpmsg_device *rpdev,
 				 const struct rpmsg_device_id *id)
 {
 	return strncmp(id->name, rpdev->id.name, RPMSG_NAME_SIZE) == 0;
@@ -163,7 +163,7 @@ static inline int rpmsg_id_match(const struct rpmsg_channel *rpdev,
 /* match rpmsg channel and rpmsg driver */
 static int rpmsg_dev_match(struct device *dev, struct device_driver *drv)
 {
-	struct rpmsg_channel *rpdev = to_rpmsg_channel(dev);
+	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
 	struct rpmsg_driver *rpdrv = to_rpmsg_driver(drv);
 	const struct rpmsg_device_id *ids = rpdrv->id_table;
 	unsigned int i;
@@ -178,7 +178,7 @@ static int rpmsg_dev_match(struct device *dev, struct device_driver *drv)
 
 static int rpmsg_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
-	struct rpmsg_channel *rpdev = to_rpmsg_channel(dev);
+	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
 
 	return add_uevent_var(env, "MODALIAS=" RPMSG_DEVICE_MODALIAS_FMT,
 					rpdev->id.name);
@@ -206,7 +206,7 @@ static void __ept_release(struct kref *kref)
 
 /* for more info, see below documentation of rpmsg_create_ept() */
 static struct rpmsg_endpoint *__rpmsg_create_ept(struct virtproc_info *vrp,
-						 struct rpmsg_channel *rpdev,
+						 struct rpmsg_device *rpdev,
 						 rpmsg_rx_cb_t cb,
 						 void *priv, u32 addr)
 {
@@ -294,7 +294,7 @@ free_ept:
  *
  * Returns a pointer to the endpoint on success, or NULL on error.
  */
-struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_channel *rpdev,
+struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev,
 					rpmsg_rx_cb_t cb, void *priv, u32 addr)
 {
 	return __rpmsg_create_ept(rpdev->vrp, rpdev, cb, priv, addr);
@@ -350,7 +350,7 @@ EXPORT_SYMBOL(rpmsg_destroy_ept);
  */
 static int rpmsg_dev_probe(struct device *dev)
 {
-	struct rpmsg_channel *rpdev = to_rpmsg_channel(dev);
+	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
 	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
 	struct virtproc_info *vrp = rpdev->vrp;
 	struct rpmsg_endpoint *ept;
@@ -393,7 +393,7 @@ out:
 
 static int rpmsg_dev_remove(struct device *dev)
 {
-	struct rpmsg_channel *rpdev = to_rpmsg_channel(dev);
+	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
 	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
 	struct virtproc_info *vrp = rpdev->vrp;
 	int err = 0;
@@ -457,7 +457,7 @@ EXPORT_SYMBOL(unregister_rpmsg_driver);
 
 static void rpmsg_release_device(struct device *dev)
 {
-	struct rpmsg_channel *rpdev = to_rpmsg_channel(dev);
+	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
 
 	kfree(rpdev);
 }
@@ -467,10 +467,10 @@ static void rpmsg_release_device(struct device *dev)
  * this is used to make sure we're not creating rpmsg devices for channels
  * that already exist.
  */
-static int rpmsg_channel_match(struct device *dev, void *data)
+static int rpmsg_device_match(struct device *dev, void *data)
 {
 	struct rpmsg_channel_info *chinfo = data;
-	struct rpmsg_channel *rpdev = to_rpmsg_channel(dev);
+	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
 
 	if (chinfo->src != RPMSG_ADDR_ANY && chinfo->src != rpdev->src)
 		return 0;
@@ -490,15 +490,15 @@ static int rpmsg_channel_match(struct device *dev, void *data)
  * this function will be used to create both static and dynamic
  * channels.
  */
-static struct rpmsg_channel *rpmsg_create_channel(struct virtproc_info *vrp,
-				struct rpmsg_channel_info *chinfo)
+static struct rpmsg_device *rpmsg_create_channel(struct virtproc_info *vrp,
+						 struct rpmsg_channel_info *chinfo)
 {
-	struct rpmsg_channel *rpdev;
+	struct rpmsg_device *rpdev;
 	struct device *tmp, *dev = &vrp->vdev->dev;
 	int ret;
 
 	/* make sure a similar channel doesn't already exist */
-	tmp = device_find_child(dev, chinfo, rpmsg_channel_match);
+	tmp = device_find_child(dev, chinfo, rpmsg_device_match);
 	if (tmp) {
 		/* decrement the matched device's refcount back */
 		put_device(tmp);
@@ -550,7 +550,7 @@ static int rpmsg_destroy_channel(struct virtproc_info *vrp,
 	struct virtio_device *vdev = vrp->vdev;
 	struct device *dev;
 
-	dev = device_find_child(&vdev->dev, chinfo, rpmsg_channel_match);
+	dev = device_find_child(&vdev->dev, chinfo, rpmsg_device_match);
 	if (!dev)
 		return -EINVAL;
 
@@ -675,7 +675,7 @@ static void rpmsg_downref_sleepers(struct virtproc_info *vrp)
  *
  * Returns 0 on success and an appropriate error value on failure.
  */
-static int rpmsg_send_offchannel_raw(struct rpmsg_channel *rpdev,
+static int rpmsg_send_offchannel_raw(struct rpmsg_device *rpdev,
 				     u32 src, u32 dst,
 				     void *data, int len, bool wait)
 {
@@ -792,7 +792,7 @@ out:
  */
 int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
 {
-	struct rpmsg_channel *rpdev = ept->rpdev;
+	struct rpmsg_device *rpdev = ept->rpdev;
 	u32 src = ept->addr, dst = rpdev->dst;
 
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
@@ -819,7 +819,7 @@ EXPORT_SYMBOL(rpmsg_send);
  */
 int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
 {
-	struct rpmsg_channel *rpdev = ept->rpdev;
+	struct rpmsg_device *rpdev = ept->rpdev;
 	u32 src = ept->addr;
 
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
@@ -849,7 +849,7 @@ EXPORT_SYMBOL(rpmsg_sendto);
 int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
 			  void *data, int len)
 {
-	struct rpmsg_channel *rpdev = ept->rpdev;
+	struct rpmsg_device *rpdev = ept->rpdev;
 
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
 }
@@ -874,7 +874,7 @@ EXPORT_SYMBOL(rpmsg_send_offchannel);
  */
 int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
 {
-	struct rpmsg_channel *rpdev = ept->rpdev;
+	struct rpmsg_device *rpdev = ept->rpdev;
 	u32 src = ept->addr, dst = rpdev->dst;
 
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
@@ -900,7 +900,7 @@ EXPORT_SYMBOL(rpmsg_trysend);
  */
 int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
 {
-	struct rpmsg_channel *rpdev = ept->rpdev;
+	struct rpmsg_device *rpdev = ept->rpdev;
 	u32 src = ept->addr;
 
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
@@ -929,7 +929,7 @@ EXPORT_SYMBOL(rpmsg_trysendto);
 int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
 			     void *data, int len)
 {
-	struct rpmsg_channel *rpdev = ept->rpdev;
+	struct rpmsg_device *rpdev = ept->rpdev;
 
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
 }
@@ -1048,11 +1048,11 @@ static void rpmsg_xmit_done(struct virtqueue *svq)
 }
 
 /* invoked when a name service announcement arrives */
-static void rpmsg_ns_cb(struct rpmsg_channel *rpdev, void *data, int len,
+static void rpmsg_ns_cb(struct rpmsg_device *rpdev, void *data, int len,
 			void *priv, u32 src)
 {
 	struct rpmsg_ns_msg *msg = data;
-	struct rpmsg_channel *newch;
+	struct rpmsg_device *newch;
 	struct rpmsg_channel_info chinfo;
 	struct virtproc_info *vrp = priv;
 	struct device *dev = &vrp->vdev->dev;
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index 554dc352d7e0..3e3d5b1c154a 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -98,7 +98,7 @@ enum rpmsg_ns_flags {
 struct virtproc_info;
 
 /**
- * rpmsg_channel - devices that belong to the rpmsg bus are called channels
+ * rpmsg_device - device that belong to the rpmsg bus
  * @vrp: the remote processor this channel belongs to
  * @dev: the device struct
  * @id: device id (used to match between rpmsg drivers and devices)
@@ -107,7 +107,7 @@ struct virtproc_info;
  * @ept: the rpmsg endpoint of this channel
  * @announce: if set, rpmsg will announce the creation/removal of this channel
  */
-struct rpmsg_channel {
+struct rpmsg_device {
 	struct virtproc_info *vrp;
 	struct device dev;
 	struct rpmsg_device_id id;
@@ -117,7 +117,7 @@ struct rpmsg_channel {
 	bool announce;
 };
 
-typedef void (*rpmsg_rx_cb_t)(struct rpmsg_channel *, void *, int, void *, u32);
+typedef void (*rpmsg_rx_cb_t)(struct rpmsg_device *, void *, int, void *, u32);
 
 /**
  * struct rpmsg_endpoint - binds a local rpmsg address to its user
@@ -143,7 +143,7 @@ typedef void (*rpmsg_rx_cb_t)(struct rpmsg_channel *, void *, int, void *, u32);
  * create additional endpoints by themselves (see rpmsg_create_ept()).
  */
 struct rpmsg_endpoint {
-	struct rpmsg_channel *rpdev;
+	struct rpmsg_device *rpdev;
 	struct kref refcount;
 	rpmsg_rx_cb_t cb;
 	struct mutex cb_lock;
@@ -162,15 +162,17 @@ struct rpmsg_endpoint {
 struct rpmsg_driver {
 	struct device_driver drv;
 	const struct rpmsg_device_id *id_table;
-	int (*probe)(struct rpmsg_channel *dev);
-	void (*remove)(struct rpmsg_channel *dev);
-	void (*callback)(struct rpmsg_channel *, void *, int, void *, u32);
+	int (*probe)(struct rpmsg_device *dev);
+	void (*remove)(struct rpmsg_device *dev);
+	void (*callback)(struct rpmsg_device *, void *, int, void *, u32);
 };
 
+int register_rpmsg_device(struct rpmsg_device *dev);
+void unregister_rpmsg_device(struct rpmsg_device *dev);
 int __register_rpmsg_driver(struct rpmsg_driver *drv, struct module *owner);
 void unregister_rpmsg_driver(struct rpmsg_driver *drv);
 void rpmsg_destroy_ept(struct rpmsg_endpoint *);
-struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_channel *,
+struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *,
 					rpmsg_rx_cb_t cb, void *priv, u32 addr);
 
 /* use a macro to avoid include chaining to get THIS_MODULE */
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 05/14] rpmsg: Unify rpmsg device vs channel naming
@ 2016-08-16  0:17   ` Bjorn Andersson
  0 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-16  0:17 UTC (permalink / raw)
  To: linux-arm-kernel

The rpmsg device representing struct is called rpmsg_channel and the
variable name used throughout is rpdev, unify these as "rpmsg device" so
that we can use the identifier "channel" for the internal object in the
future.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/rpmsg/virtio_rpmsg_bus.c | 54 ++++++++++++++++++++--------------------
 include/linux/rpmsg.h            | 18 ++++++++------
 2 files changed, 37 insertions(+), 35 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index f8fb9e065821..a9f8cc8d968b 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -85,7 +85,7 @@ struct rpmsg_channel_info {
 	u32 dst;
 };
 
-#define to_rpmsg_channel(d) container_of(d, struct rpmsg_channel, dev)
+#define to_rpmsg_device(d) container_of(d, struct rpmsg_device, dev)
 #define to_rpmsg_driver(d) container_of(d, struct rpmsg_driver, drv)
 
 /*
@@ -125,7 +125,7 @@ static ssize_t								\
 field##_show(struct device *dev,					\
 			struct device_attribute *attr, char *buf)	\
 {									\
-	struct rpmsg_channel *rpdev = to_rpmsg_channel(dev);		\
+	struct rpmsg_device *rpdev = to_rpmsg_device(dev);		\
 									\
 	return sprintf(buf, format_string, rpdev->path);		\
 }
@@ -139,7 +139,7 @@ rpmsg_show_attr(announce, announce ? "true" : "false", "%s\n");
 static ssize_t modalias_show(struct device *dev,
 			     struct device_attribute *attr, char *buf)
 {
-	struct rpmsg_channel *rpdev = to_rpmsg_channel(dev);
+	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
 
 	return sprintf(buf, RPMSG_DEVICE_MODALIAS_FMT "\n", rpdev->id.name);
 }
@@ -154,7 +154,7 @@ static struct device_attribute rpmsg_dev_attrs[] = {
 };
 
 /* rpmsg devices and drivers are matched using the service name */
-static inline int rpmsg_id_match(const struct rpmsg_channel *rpdev,
+static inline int rpmsg_id_match(const struct rpmsg_device *rpdev,
 				 const struct rpmsg_device_id *id)
 {
 	return strncmp(id->name, rpdev->id.name, RPMSG_NAME_SIZE) == 0;
@@ -163,7 +163,7 @@ static inline int rpmsg_id_match(const struct rpmsg_channel *rpdev,
 /* match rpmsg channel and rpmsg driver */
 static int rpmsg_dev_match(struct device *dev, struct device_driver *drv)
 {
-	struct rpmsg_channel *rpdev = to_rpmsg_channel(dev);
+	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
 	struct rpmsg_driver *rpdrv = to_rpmsg_driver(drv);
 	const struct rpmsg_device_id *ids = rpdrv->id_table;
 	unsigned int i;
@@ -178,7 +178,7 @@ static int rpmsg_dev_match(struct device *dev, struct device_driver *drv)
 
 static int rpmsg_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
-	struct rpmsg_channel *rpdev = to_rpmsg_channel(dev);
+	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
 
 	return add_uevent_var(env, "MODALIAS=" RPMSG_DEVICE_MODALIAS_FMT,
 					rpdev->id.name);
@@ -206,7 +206,7 @@ static void __ept_release(struct kref *kref)
 
 /* for more info, see below documentation of rpmsg_create_ept() */
 static struct rpmsg_endpoint *__rpmsg_create_ept(struct virtproc_info *vrp,
-						 struct rpmsg_channel *rpdev,
+						 struct rpmsg_device *rpdev,
 						 rpmsg_rx_cb_t cb,
 						 void *priv, u32 addr)
 {
@@ -294,7 +294,7 @@ free_ept:
  *
  * Returns a pointer to the endpoint on success, or NULL on error.
  */
-struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_channel *rpdev,
+struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev,
 					rpmsg_rx_cb_t cb, void *priv, u32 addr)
 {
 	return __rpmsg_create_ept(rpdev->vrp, rpdev, cb, priv, addr);
@@ -350,7 +350,7 @@ EXPORT_SYMBOL(rpmsg_destroy_ept);
  */
 static int rpmsg_dev_probe(struct device *dev)
 {
-	struct rpmsg_channel *rpdev = to_rpmsg_channel(dev);
+	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
 	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
 	struct virtproc_info *vrp = rpdev->vrp;
 	struct rpmsg_endpoint *ept;
@@ -393,7 +393,7 @@ out:
 
 static int rpmsg_dev_remove(struct device *dev)
 {
-	struct rpmsg_channel *rpdev = to_rpmsg_channel(dev);
+	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
 	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
 	struct virtproc_info *vrp = rpdev->vrp;
 	int err = 0;
@@ -457,7 +457,7 @@ EXPORT_SYMBOL(unregister_rpmsg_driver);
 
 static void rpmsg_release_device(struct device *dev)
 {
-	struct rpmsg_channel *rpdev = to_rpmsg_channel(dev);
+	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
 
 	kfree(rpdev);
 }
@@ -467,10 +467,10 @@ static void rpmsg_release_device(struct device *dev)
  * this is used to make sure we're not creating rpmsg devices for channels
  * that already exist.
  */
-static int rpmsg_channel_match(struct device *dev, void *data)
+static int rpmsg_device_match(struct device *dev, void *data)
 {
 	struct rpmsg_channel_info *chinfo = data;
-	struct rpmsg_channel *rpdev = to_rpmsg_channel(dev);
+	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
 
 	if (chinfo->src != RPMSG_ADDR_ANY && chinfo->src != rpdev->src)
 		return 0;
@@ -490,15 +490,15 @@ static int rpmsg_channel_match(struct device *dev, void *data)
  * this function will be used to create both static and dynamic
  * channels.
  */
-static struct rpmsg_channel *rpmsg_create_channel(struct virtproc_info *vrp,
-				struct rpmsg_channel_info *chinfo)
+static struct rpmsg_device *rpmsg_create_channel(struct virtproc_info *vrp,
+						 struct rpmsg_channel_info *chinfo)
 {
-	struct rpmsg_channel *rpdev;
+	struct rpmsg_device *rpdev;
 	struct device *tmp, *dev = &vrp->vdev->dev;
 	int ret;
 
 	/* make sure a similar channel doesn't already exist */
-	tmp = device_find_child(dev, chinfo, rpmsg_channel_match);
+	tmp = device_find_child(dev, chinfo, rpmsg_device_match);
 	if (tmp) {
 		/* decrement the matched device's refcount back */
 		put_device(tmp);
@@ -550,7 +550,7 @@ static int rpmsg_destroy_channel(struct virtproc_info *vrp,
 	struct virtio_device *vdev = vrp->vdev;
 	struct device *dev;
 
-	dev = device_find_child(&vdev->dev, chinfo, rpmsg_channel_match);
+	dev = device_find_child(&vdev->dev, chinfo, rpmsg_device_match);
 	if (!dev)
 		return -EINVAL;
 
@@ -675,7 +675,7 @@ static void rpmsg_downref_sleepers(struct virtproc_info *vrp)
  *
  * Returns 0 on success and an appropriate error value on failure.
  */
-static int rpmsg_send_offchannel_raw(struct rpmsg_channel *rpdev,
+static int rpmsg_send_offchannel_raw(struct rpmsg_device *rpdev,
 				     u32 src, u32 dst,
 				     void *data, int len, bool wait)
 {
@@ -792,7 +792,7 @@ out:
  */
 int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
 {
-	struct rpmsg_channel *rpdev = ept->rpdev;
+	struct rpmsg_device *rpdev = ept->rpdev;
 	u32 src = ept->addr, dst = rpdev->dst;
 
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
@@ -819,7 +819,7 @@ EXPORT_SYMBOL(rpmsg_send);
  */
 int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
 {
-	struct rpmsg_channel *rpdev = ept->rpdev;
+	struct rpmsg_device *rpdev = ept->rpdev;
 	u32 src = ept->addr;
 
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
@@ -849,7 +849,7 @@ EXPORT_SYMBOL(rpmsg_sendto);
 int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
 			  void *data, int len)
 {
-	struct rpmsg_channel *rpdev = ept->rpdev;
+	struct rpmsg_device *rpdev = ept->rpdev;
 
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
 }
@@ -874,7 +874,7 @@ EXPORT_SYMBOL(rpmsg_send_offchannel);
  */
 int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
 {
-	struct rpmsg_channel *rpdev = ept->rpdev;
+	struct rpmsg_device *rpdev = ept->rpdev;
 	u32 src = ept->addr, dst = rpdev->dst;
 
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
@@ -900,7 +900,7 @@ EXPORT_SYMBOL(rpmsg_trysend);
  */
 int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
 {
-	struct rpmsg_channel *rpdev = ept->rpdev;
+	struct rpmsg_device *rpdev = ept->rpdev;
 	u32 src = ept->addr;
 
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
@@ -929,7 +929,7 @@ EXPORT_SYMBOL(rpmsg_trysendto);
 int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
 			     void *data, int len)
 {
-	struct rpmsg_channel *rpdev = ept->rpdev;
+	struct rpmsg_device *rpdev = ept->rpdev;
 
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
 }
@@ -1048,11 +1048,11 @@ static void rpmsg_xmit_done(struct virtqueue *svq)
 }
 
 /* invoked when a name service announcement arrives */
-static void rpmsg_ns_cb(struct rpmsg_channel *rpdev, void *data, int len,
+static void rpmsg_ns_cb(struct rpmsg_device *rpdev, void *data, int len,
 			void *priv, u32 src)
 {
 	struct rpmsg_ns_msg *msg = data;
-	struct rpmsg_channel *newch;
+	struct rpmsg_device *newch;
 	struct rpmsg_channel_info chinfo;
 	struct virtproc_info *vrp = priv;
 	struct device *dev = &vrp->vdev->dev;
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index 554dc352d7e0..3e3d5b1c154a 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -98,7 +98,7 @@ enum rpmsg_ns_flags {
 struct virtproc_info;
 
 /**
- * rpmsg_channel - devices that belong to the rpmsg bus are called channels
+ * rpmsg_device - device that belong to the rpmsg bus
  * @vrp: the remote processor this channel belongs to
  * @dev: the device struct
  * @id: device id (used to match between rpmsg drivers and devices)
@@ -107,7 +107,7 @@ struct virtproc_info;
  * @ept: the rpmsg endpoint of this channel
  * @announce: if set, rpmsg will announce the creation/removal of this channel
  */
-struct rpmsg_channel {
+struct rpmsg_device {
 	struct virtproc_info *vrp;
 	struct device dev;
 	struct rpmsg_device_id id;
@@ -117,7 +117,7 @@ struct rpmsg_channel {
 	bool announce;
 };
 
-typedef void (*rpmsg_rx_cb_t)(struct rpmsg_channel *, void *, int, void *, u32);
+typedef void (*rpmsg_rx_cb_t)(struct rpmsg_device *, void *, int, void *, u32);
 
 /**
  * struct rpmsg_endpoint - binds a local rpmsg address to its user
@@ -143,7 +143,7 @@ typedef void (*rpmsg_rx_cb_t)(struct rpmsg_channel *, void *, int, void *, u32);
  * create additional endpoints by themselves (see rpmsg_create_ept()).
  */
 struct rpmsg_endpoint {
-	struct rpmsg_channel *rpdev;
+	struct rpmsg_device *rpdev;
 	struct kref refcount;
 	rpmsg_rx_cb_t cb;
 	struct mutex cb_lock;
@@ -162,15 +162,17 @@ struct rpmsg_endpoint {
 struct rpmsg_driver {
 	struct device_driver drv;
 	const struct rpmsg_device_id *id_table;
-	int (*probe)(struct rpmsg_channel *dev);
-	void (*remove)(struct rpmsg_channel *dev);
-	void (*callback)(struct rpmsg_channel *, void *, int, void *, u32);
+	int (*probe)(struct rpmsg_device *dev);
+	void (*remove)(struct rpmsg_device *dev);
+	void (*callback)(struct rpmsg_device *, void *, int, void *, u32);
 };
 
+int register_rpmsg_device(struct rpmsg_device *dev);
+void unregister_rpmsg_device(struct rpmsg_device *dev);
 int __register_rpmsg_driver(struct rpmsg_driver *drv, struct module *owner);
 void unregister_rpmsg_driver(struct rpmsg_driver *drv);
 void rpmsg_destroy_ept(struct rpmsg_endpoint *);
-struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_channel *,
+struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *,
 					rpmsg_rx_cb_t cb, void *priv, u32 addr);
 
 /* use a macro to avoid include chaining to get THIS_MODULE */
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 06/14] rpmsg: Indirect all virtio related function calls
  2016-08-16  0:17 ` Bjorn Andersson
@ 2016-08-16  0:17   ` Bjorn Andersson
  -1 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-16  0:17 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson
  Cc: linux-remoteproc, linux-arm-msm, linux-arm-kernel, linux-kernel

Create indirections for functions in prepration for splitting the rpmsg
core functionality from the virtio backend.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/rpmsg/virtio_rpmsg_bus.c | 131 +++++++++++++++++++++++++++++++++++----
 include/linux/rpmsg.h            |  23 ++++++-
 2 files changed, 139 insertions(+), 15 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index a9f8cc8d968b..1dc7a1149c51 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -119,6 +119,17 @@ struct rpmsg_channel_info {
 /* Address 53 is reserved for advertising remote services */
 #define RPMSG_NS_ADDR			(53)
 
+static int virtio_rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len);
+static int virtio_rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len,
+			       u32 dst);
+static int virtio_rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src,
+					u32 dst, void *data, int len);
+static int virtio_rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len);
+static int virtio_rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data,
+				  int len, u32 dst);
+static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src,
+					   u32 dst, void *data, int len);
+
 /* sysfs show configuration fields */
 #define rpmsg_show_attr(field, path, format_string)			\
 static ssize_t								\
@@ -297,10 +308,17 @@ free_ept:
 struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev,
 					rpmsg_rx_cb_t cb, void *priv, u32 addr)
 {
-	return __rpmsg_create_ept(rpdev->vrp, rpdev, cb, priv, addr);
+	return rpdev->create_ept(rpdev, cb, priv, addr);
 }
 EXPORT_SYMBOL(rpmsg_create_ept);
 
+static struct rpmsg_endpoint *virtio_rpmsg_create_ept(struct rpmsg_device *rpdev,
+						      rpmsg_rx_cb_t cb,
+						      void *priv, u32 addr)
+{
+	return __rpmsg_create_ept(rpdev->vrp, rpdev, cb, priv, addr);
+}
+
 /**
  * __rpmsg_destroy_ept() - destroy an existing rpmsg endpoint
  * @vrp: virtproc which owns this ept
@@ -336,10 +354,15 @@ __rpmsg_destroy_ept(struct virtproc_info *vrp, struct rpmsg_endpoint *ept)
  */
 void rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
 {
-	__rpmsg_destroy_ept(ept->rpdev->vrp, ept);
+	ept->rpdev->destroy_ept(ept);
 }
 EXPORT_SYMBOL(rpmsg_destroy_ept);
 
+static void virtio_rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
+{
+	__rpmsg_destroy_ept(ept->rpdev->vrp, ept);
+}
+
 /*
  * when an rpmsg driver is probed with a channel, we seamlessly create
  * it an endpoint, binding its rx callback to a unique local rpmsg
@@ -352,7 +375,6 @@ static int rpmsg_dev_probe(struct device *dev)
 {
 	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
 	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
-	struct virtproc_info *vrp = rpdev->vrp;
 	struct rpmsg_endpoint *ept;
 	int err;
 
@@ -373,6 +395,18 @@ static int rpmsg_dev_probe(struct device *dev)
 		goto out;
 	}
 
+	if (rpdev->announce_create)
+		err = rpdev->announce_create(rpdev);
+out:
+	return err;
+}
+
+static int virtio_rpmsg_announce_create(struct rpmsg_device *rpdev)
+{
+	struct virtproc_info *vrp = rpdev->vrp;
+	struct device *dev = &rpdev->dev;
+	int err = 0;
+
 	/* need to tell remote processor's name service about this channel ? */
 	if (rpdev->announce &&
 	    virtio_has_feature(vrp->vdev, VIRTIO_RPMSG_F_NS)) {
@@ -387,15 +421,13 @@ static int rpmsg_dev_probe(struct device *dev)
 			dev_err(dev, "failed to announce service %d\n", err);
 	}
 
-out:
 	return err;
 }
 
-static int rpmsg_dev_remove(struct device *dev)
+static int virtio_rpmsg_announce_destroy(struct rpmsg_device *rpdev)
 {
-	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
-	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
 	struct virtproc_info *vrp = rpdev->vrp;
+	struct device *dev = &rpdev->dev;
 	int err = 0;
 
 	/* tell remote processor's name service we're removing this channel */
@@ -412,6 +444,18 @@ static int rpmsg_dev_remove(struct device *dev)
 			dev_err(dev, "failed to announce service %d\n", err);
 	}
 
+	return err;
+}
+
+static int rpmsg_dev_remove(struct device *dev)
+{
+	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
+	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
+	int err = 0;
+
+	if (rpdev->announce_destroy)
+		err = rpdev->announce_destroy(rpdev);
+
 	rpdrv->remove(rpdev);
 
 	rpmsg_destroy_ept(rpdev->ept);
@@ -485,6 +529,19 @@ static int rpmsg_device_match(struct device *dev, void *data)
 	return 1;
 }
 
+static const struct rpmsg_device virtio_rpmsg_ops = {
+	.create_ept = virtio_rpmsg_create_ept,
+	.destroy_ept = virtio_rpmsg_destroy_ept,
+	.send = virtio_rpmsg_send,
+	.sendto = virtio_rpmsg_sendto,
+	.send_offchannel = virtio_rpmsg_send_offchannel,
+	.trysend = virtio_rpmsg_trysend,
+	.trysendto = virtio_rpmsg_trysendto,
+	.trysend_offchannel = virtio_rpmsg_trysend_offchannel,
+	.announce_create = virtio_rpmsg_announce_create,
+	.announce_destroy = virtio_rpmsg_announce_destroy,
+};
+
 /*
  * create an rpmsg channel using its name and address info.
  * this function will be used to create both static and dynamic
@@ -511,6 +568,9 @@ static struct rpmsg_device *rpmsg_create_channel(struct virtproc_info *vrp,
 	if (!rpdev)
 		return NULL;
 
+	/* Assign callbacks for rpmsg_channel */
+	*rpdev = virtio_rpmsg_ops;
+
 	rpdev->vrp = vrp;
 	rpdev->src = chinfo->src;
 	rpdev->dst = chinfo->dst;
@@ -793,11 +853,17 @@ out:
 int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
 {
 	struct rpmsg_device *rpdev = ept->rpdev;
+
+	return rpdev->send(ept, data, len);
+}
+
+static int virtio_rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
+{
+	struct rpmsg_device *rpdev = ept->rpdev;
 	u32 src = ept->addr, dst = rpdev->dst;
 
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
 }
-EXPORT_SYMBOL(rpmsg_send);
 
 /**
  * rpmsg_sendto() - send a message across to the remote processor, specify dst
@@ -820,11 +886,19 @@ EXPORT_SYMBOL(rpmsg_send);
 int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
 {
 	struct rpmsg_device *rpdev = ept->rpdev;
+
+	return rpdev->sendto(ept, data, len, dst);
+}
+EXPORT_SYMBOL(rpmsg_sendto);
+
+static int virtio_rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len,
+			       u32 dst)
+{
+	struct rpmsg_device *rpdev = ept->rpdev;
 	u32 src = ept->addr;
 
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
 }
-EXPORT_SYMBOL(rpmsg_sendto);
 
 /**
  * rpmsg_send_offchannel() - send a message using explicit src/dst addresses
@@ -851,10 +925,18 @@ int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
 {
 	struct rpmsg_device *rpdev = ept->rpdev;
 
-	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
+	return rpdev->send_offchannel(ept, src, dst, data, len);
 }
 EXPORT_SYMBOL(rpmsg_send_offchannel);
 
+static int virtio_rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src,
+					u32 dst, void *data, int len)
+{
+	struct rpmsg_device *rpdev = ept->rpdev;
+
+	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
+}
+
 /**
  * rpmsg_send() - send a message across to the remote processor
  * @ept: the rpmsg endpoint
@@ -875,11 +957,18 @@ EXPORT_SYMBOL(rpmsg_send_offchannel);
 int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
 {
 	struct rpmsg_device *rpdev = ept->rpdev;
+
+	return rpdev->trysend(ept, data, len);
+}
+EXPORT_SYMBOL(rpmsg_trysend);
+
+static int virtio_rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
+{
+	struct rpmsg_device *rpdev = ept->rpdev;
 	u32 src = ept->addr, dst = rpdev->dst;
 
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
 }
-EXPORT_SYMBOL(rpmsg_trysend);
 
 /**
  * rpmsg_sendto() - send a message across to the remote processor, specify dst
@@ -901,11 +990,19 @@ EXPORT_SYMBOL(rpmsg_trysend);
 int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
 {
 	struct rpmsg_device *rpdev = ept->rpdev;
+
+	return rpdev->trysendto(ept, data, len, dst);
+}
+EXPORT_SYMBOL(rpmsg_trysendto);
+
+static int virtio_rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data,
+				  int len, u32 dst)
+{
+	struct rpmsg_device *rpdev = ept->rpdev;
 	u32 src = ept->addr;
 
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
 }
-EXPORT_SYMBOL(rpmsg_trysendto);
 
 /**
  * rpmsg_send_offchannel() - send a message using explicit src/dst addresses
@@ -931,10 +1028,18 @@ int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
 {
 	struct rpmsg_device *rpdev = ept->rpdev;
 
-	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
+	return rpdev->trysend_offchannel(ept, src, dst, data, len);
 }
 EXPORT_SYMBOL(rpmsg_trysend_offchannel);
 
+static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src,
+					   u32 dst, void *data, int len)
+{
+	struct rpmsg_device *rpdev = ept->rpdev;
+
+	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
+}
+
 static int rpmsg_recv_single(struct virtproc_info *vrp, struct device *dev,
 			     struct rpmsg_hdr *msg, unsigned int len)
 {
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index 3e3d5b1c154a..0b290ae18e70 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -96,6 +96,10 @@ enum rpmsg_ns_flags {
 #define RPMSG_ADDR_ANY		0xFFFFFFFF
 
 struct virtproc_info;
+struct rpmsg_device;
+struct rpmsg_endpoint;
+
+typedef void (*rpmsg_rx_cb_t)(struct rpmsg_device *, void *, int, void *, u32);
 
 /**
  * rpmsg_device - device that belong to the rpmsg bus
@@ -115,9 +119,24 @@ struct rpmsg_device {
 	u32 dst;
 	struct rpmsg_endpoint *ept;
 	bool announce;
-};
 
-typedef void (*rpmsg_rx_cb_t)(struct rpmsg_device *, void *, int, void *, u32);
+	struct rpmsg_endpoint *(*create_ept)(struct rpmsg_device *rpdev,
+					    rpmsg_rx_cb_t cb, void *priv, u32 addr);
+	void (*destroy_ept)(struct rpmsg_endpoint *ept);
+
+	int (*send)(struct rpmsg_endpoint *ept, void *data, int len);
+	int (*sendto)(struct rpmsg_endpoint *ept, void *data, int len, u32 dst);
+	int (*send_offchannel)(struct rpmsg_endpoint *ept, u32 src, u32 dst,
+				  void *data, int len);
+
+	int (*trysend)(struct rpmsg_endpoint *ept, void *data, int len);
+	int (*trysendto)(struct rpmsg_endpoint *ept, void *data, int len, u32 dst);
+	int (*trysend_offchannel)(struct rpmsg_endpoint *ept, u32 src, u32 dst,
+			     void *data, int len);
+
+	int (*announce_create)(struct rpmsg_device *ept);
+	int (*announce_destroy)(struct rpmsg_device *ept);
+};
 
 /**
  * struct rpmsg_endpoint - binds a local rpmsg address to its user
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 06/14] rpmsg: Indirect all virtio related function calls
@ 2016-08-16  0:17   ` Bjorn Andersson
  0 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-16  0:17 UTC (permalink / raw)
  To: linux-arm-kernel

Create indirections for functions in prepration for splitting the rpmsg
core functionality from the virtio backend.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/rpmsg/virtio_rpmsg_bus.c | 131 +++++++++++++++++++++++++++++++++++----
 include/linux/rpmsg.h            |  23 ++++++-
 2 files changed, 139 insertions(+), 15 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index a9f8cc8d968b..1dc7a1149c51 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -119,6 +119,17 @@ struct rpmsg_channel_info {
 /* Address 53 is reserved for advertising remote services */
 #define RPMSG_NS_ADDR			(53)
 
+static int virtio_rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len);
+static int virtio_rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len,
+			       u32 dst);
+static int virtio_rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src,
+					u32 dst, void *data, int len);
+static int virtio_rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len);
+static int virtio_rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data,
+				  int len, u32 dst);
+static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src,
+					   u32 dst, void *data, int len);
+
 /* sysfs show configuration fields */
 #define rpmsg_show_attr(field, path, format_string)			\
 static ssize_t								\
@@ -297,10 +308,17 @@ free_ept:
 struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev,
 					rpmsg_rx_cb_t cb, void *priv, u32 addr)
 {
-	return __rpmsg_create_ept(rpdev->vrp, rpdev, cb, priv, addr);
+	return rpdev->create_ept(rpdev, cb, priv, addr);
 }
 EXPORT_SYMBOL(rpmsg_create_ept);
 
+static struct rpmsg_endpoint *virtio_rpmsg_create_ept(struct rpmsg_device *rpdev,
+						      rpmsg_rx_cb_t cb,
+						      void *priv, u32 addr)
+{
+	return __rpmsg_create_ept(rpdev->vrp, rpdev, cb, priv, addr);
+}
+
 /**
  * __rpmsg_destroy_ept() - destroy an existing rpmsg endpoint
  * @vrp: virtproc which owns this ept
@@ -336,10 +354,15 @@ __rpmsg_destroy_ept(struct virtproc_info *vrp, struct rpmsg_endpoint *ept)
  */
 void rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
 {
-	__rpmsg_destroy_ept(ept->rpdev->vrp, ept);
+	ept->rpdev->destroy_ept(ept);
 }
 EXPORT_SYMBOL(rpmsg_destroy_ept);
 
+static void virtio_rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
+{
+	__rpmsg_destroy_ept(ept->rpdev->vrp, ept);
+}
+
 /*
  * when an rpmsg driver is probed with a channel, we seamlessly create
  * it an endpoint, binding its rx callback to a unique local rpmsg
@@ -352,7 +375,6 @@ static int rpmsg_dev_probe(struct device *dev)
 {
 	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
 	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
-	struct virtproc_info *vrp = rpdev->vrp;
 	struct rpmsg_endpoint *ept;
 	int err;
 
@@ -373,6 +395,18 @@ static int rpmsg_dev_probe(struct device *dev)
 		goto out;
 	}
 
+	if (rpdev->announce_create)
+		err = rpdev->announce_create(rpdev);
+out:
+	return err;
+}
+
+static int virtio_rpmsg_announce_create(struct rpmsg_device *rpdev)
+{
+	struct virtproc_info *vrp = rpdev->vrp;
+	struct device *dev = &rpdev->dev;
+	int err = 0;
+
 	/* need to tell remote processor's name service about this channel ? */
 	if (rpdev->announce &&
 	    virtio_has_feature(vrp->vdev, VIRTIO_RPMSG_F_NS)) {
@@ -387,15 +421,13 @@ static int rpmsg_dev_probe(struct device *dev)
 			dev_err(dev, "failed to announce service %d\n", err);
 	}
 
-out:
 	return err;
 }
 
-static int rpmsg_dev_remove(struct device *dev)
+static int virtio_rpmsg_announce_destroy(struct rpmsg_device *rpdev)
 {
-	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
-	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
 	struct virtproc_info *vrp = rpdev->vrp;
+	struct device *dev = &rpdev->dev;
 	int err = 0;
 
 	/* tell remote processor's name service we're removing this channel */
@@ -412,6 +444,18 @@ static int rpmsg_dev_remove(struct device *dev)
 			dev_err(dev, "failed to announce service %d\n", err);
 	}
 
+	return err;
+}
+
+static int rpmsg_dev_remove(struct device *dev)
+{
+	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
+	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
+	int err = 0;
+
+	if (rpdev->announce_destroy)
+		err = rpdev->announce_destroy(rpdev);
+
 	rpdrv->remove(rpdev);
 
 	rpmsg_destroy_ept(rpdev->ept);
@@ -485,6 +529,19 @@ static int rpmsg_device_match(struct device *dev, void *data)
 	return 1;
 }
 
+static const struct rpmsg_device virtio_rpmsg_ops = {
+	.create_ept = virtio_rpmsg_create_ept,
+	.destroy_ept = virtio_rpmsg_destroy_ept,
+	.send = virtio_rpmsg_send,
+	.sendto = virtio_rpmsg_sendto,
+	.send_offchannel = virtio_rpmsg_send_offchannel,
+	.trysend = virtio_rpmsg_trysend,
+	.trysendto = virtio_rpmsg_trysendto,
+	.trysend_offchannel = virtio_rpmsg_trysend_offchannel,
+	.announce_create = virtio_rpmsg_announce_create,
+	.announce_destroy = virtio_rpmsg_announce_destroy,
+};
+
 /*
  * create an rpmsg channel using its name and address info.
  * this function will be used to create both static and dynamic
@@ -511,6 +568,9 @@ static struct rpmsg_device *rpmsg_create_channel(struct virtproc_info *vrp,
 	if (!rpdev)
 		return NULL;
 
+	/* Assign callbacks for rpmsg_channel */
+	*rpdev = virtio_rpmsg_ops;
+
 	rpdev->vrp = vrp;
 	rpdev->src = chinfo->src;
 	rpdev->dst = chinfo->dst;
@@ -793,11 +853,17 @@ out:
 int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
 {
 	struct rpmsg_device *rpdev = ept->rpdev;
+
+	return rpdev->send(ept, data, len);
+}
+
+static int virtio_rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
+{
+	struct rpmsg_device *rpdev = ept->rpdev;
 	u32 src = ept->addr, dst = rpdev->dst;
 
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
 }
-EXPORT_SYMBOL(rpmsg_send);
 
 /**
  * rpmsg_sendto() - send a message across to the remote processor, specify dst
@@ -820,11 +886,19 @@ EXPORT_SYMBOL(rpmsg_send);
 int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
 {
 	struct rpmsg_device *rpdev = ept->rpdev;
+
+	return rpdev->sendto(ept, data, len, dst);
+}
+EXPORT_SYMBOL(rpmsg_sendto);
+
+static int virtio_rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len,
+			       u32 dst)
+{
+	struct rpmsg_device *rpdev = ept->rpdev;
 	u32 src = ept->addr;
 
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
 }
-EXPORT_SYMBOL(rpmsg_sendto);
 
 /**
  * rpmsg_send_offchannel() - send a message using explicit src/dst addresses
@@ -851,10 +925,18 @@ int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
 {
 	struct rpmsg_device *rpdev = ept->rpdev;
 
-	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
+	return rpdev->send_offchannel(ept, src, dst, data, len);
 }
 EXPORT_SYMBOL(rpmsg_send_offchannel);
 
+static int virtio_rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src,
+					u32 dst, void *data, int len)
+{
+	struct rpmsg_device *rpdev = ept->rpdev;
+
+	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
+}
+
 /**
  * rpmsg_send() - send a message across to the remote processor
  * @ept: the rpmsg endpoint
@@ -875,11 +957,18 @@ EXPORT_SYMBOL(rpmsg_send_offchannel);
 int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
 {
 	struct rpmsg_device *rpdev = ept->rpdev;
+
+	return rpdev->trysend(ept, data, len);
+}
+EXPORT_SYMBOL(rpmsg_trysend);
+
+static int virtio_rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
+{
+	struct rpmsg_device *rpdev = ept->rpdev;
 	u32 src = ept->addr, dst = rpdev->dst;
 
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
 }
-EXPORT_SYMBOL(rpmsg_trysend);
 
 /**
  * rpmsg_sendto() - send a message across to the remote processor, specify dst
@@ -901,11 +990,19 @@ EXPORT_SYMBOL(rpmsg_trysend);
 int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
 {
 	struct rpmsg_device *rpdev = ept->rpdev;
+
+	return rpdev->trysendto(ept, data, len, dst);
+}
+EXPORT_SYMBOL(rpmsg_trysendto);
+
+static int virtio_rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data,
+				  int len, u32 dst)
+{
+	struct rpmsg_device *rpdev = ept->rpdev;
 	u32 src = ept->addr;
 
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
 }
-EXPORT_SYMBOL(rpmsg_trysendto);
 
 /**
  * rpmsg_send_offchannel() - send a message using explicit src/dst addresses
@@ -931,10 +1028,18 @@ int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
 {
 	struct rpmsg_device *rpdev = ept->rpdev;
 
-	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
+	return rpdev->trysend_offchannel(ept, src, dst, data, len);
 }
 EXPORT_SYMBOL(rpmsg_trysend_offchannel);
 
+static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src,
+					   u32 dst, void *data, int len)
+{
+	struct rpmsg_device *rpdev = ept->rpdev;
+
+	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
+}
+
 static int rpmsg_recv_single(struct virtproc_info *vrp, struct device *dev,
 			     struct rpmsg_hdr *msg, unsigned int len)
 {
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index 3e3d5b1c154a..0b290ae18e70 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -96,6 +96,10 @@ enum rpmsg_ns_flags {
 #define RPMSG_ADDR_ANY		0xFFFFFFFF
 
 struct virtproc_info;
+struct rpmsg_device;
+struct rpmsg_endpoint;
+
+typedef void (*rpmsg_rx_cb_t)(struct rpmsg_device *, void *, int, void *, u32);
 
 /**
  * rpmsg_device - device that belong to the rpmsg bus
@@ -115,9 +119,24 @@ struct rpmsg_device {
 	u32 dst;
 	struct rpmsg_endpoint *ept;
 	bool announce;
-};
 
-typedef void (*rpmsg_rx_cb_t)(struct rpmsg_device *, void *, int, void *, u32);
+	struct rpmsg_endpoint *(*create_ept)(struct rpmsg_device *rpdev,
+					    rpmsg_rx_cb_t cb, void *priv, u32 addr);
+	void (*destroy_ept)(struct rpmsg_endpoint *ept);
+
+	int (*send)(struct rpmsg_endpoint *ept, void *data, int len);
+	int (*sendto)(struct rpmsg_endpoint *ept, void *data, int len, u32 dst);
+	int (*send_offchannel)(struct rpmsg_endpoint *ept, u32 src, u32 dst,
+				  void *data, int len);
+
+	int (*trysend)(struct rpmsg_endpoint *ept, void *data, int len);
+	int (*trysendto)(struct rpmsg_endpoint *ept, void *data, int len, u32 dst);
+	int (*trysend_offchannel)(struct rpmsg_endpoint *ept, u32 src, u32 dst,
+			     void *data, int len);
+
+	int (*announce_create)(struct rpmsg_device *ept);
+	int (*announce_destroy)(struct rpmsg_device *ept);
+};
 
 /**
  * struct rpmsg_endpoint - binds a local rpmsg address to its user
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 07/14] rpmsg: Split off generic tail of create_channel()
  2016-08-16  0:17 ` Bjorn Andersson
@ 2016-08-16  0:17   ` Bjorn Andersson
  -1 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-16  0:17 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson
  Cc: linux-remoteproc, linux-arm-msm, linux-arm-kernel, linux-kernel

The tail of create_channel() is common among all rpmsg backends, so
split it off from the virtio specific part to allow it to be extracted
to the rpmsg core.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/rpmsg/virtio_rpmsg_bus.c | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 1dc7a1149c51..5cadb75a225d 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -129,6 +129,7 @@ static int virtio_rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data,
 				  int len, u32 dst);
 static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src,
 					   u32 dst, void *data, int len);
+static int rpmsg_register_device(struct rpmsg_device *rpdev);
 
 /* sysfs show configuration fields */
 #define rpmsg_show_attr(field, path, format_string)			\
@@ -583,10 +584,22 @@ static struct rpmsg_device *rpmsg_create_channel(struct virtproc_info *vrp,
 
 	strncpy(rpdev->id.name, chinfo->name, RPMSG_NAME_SIZE);
 
+	rpdev->dev.parent = &vrp->vdev->dev;
+	ret = rpmsg_register_device(rpdev);
+	if (ret)
+		return NULL;
+
+	return rpdev;
+}
+
+static int rpmsg_register_device(struct rpmsg_device *rpdev)
+{
+	struct device *dev = &rpdev->dev;
+	int ret;
+
 	dev_set_name(&rpdev->dev, "%s:%s",
 		     dev_name(dev->parent), rpdev->id.name);
 
-	rpdev->dev.parent = &vrp->vdev->dev;
 	rpdev->dev.bus = &rpmsg_bus;
 	rpdev->dev.release = rpmsg_release_device;
 
@@ -594,10 +607,9 @@ static struct rpmsg_device *rpmsg_create_channel(struct virtproc_info *vrp,
 	if (ret) {
 		dev_err(dev, "device_register failed: %d\n", ret);
 		put_device(&rpdev->dev);
-		return NULL;
 	}
 
-	return rpdev;
+	return ret;
 }
 
 /*
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 07/14] rpmsg: Split off generic tail of create_channel()
@ 2016-08-16  0:17   ` Bjorn Andersson
  0 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-16  0:17 UTC (permalink / raw)
  To: linux-arm-kernel

The tail of create_channel() is common among all rpmsg backends, so
split it off from the virtio specific part to allow it to be extracted
to the rpmsg core.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/rpmsg/virtio_rpmsg_bus.c | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 1dc7a1149c51..5cadb75a225d 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -129,6 +129,7 @@ static int virtio_rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data,
 				  int len, u32 dst);
 static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src,
 					   u32 dst, void *data, int len);
+static int rpmsg_register_device(struct rpmsg_device *rpdev);
 
 /* sysfs show configuration fields */
 #define rpmsg_show_attr(field, path, format_string)			\
@@ -583,10 +584,22 @@ static struct rpmsg_device *rpmsg_create_channel(struct virtproc_info *vrp,
 
 	strncpy(rpdev->id.name, chinfo->name, RPMSG_NAME_SIZE);
 
+	rpdev->dev.parent = &vrp->vdev->dev;
+	ret = rpmsg_register_device(rpdev);
+	if (ret)
+		return NULL;
+
+	return rpdev;
+}
+
+static int rpmsg_register_device(struct rpmsg_device *rpdev)
+{
+	struct device *dev = &rpdev->dev;
+	int ret;
+
 	dev_set_name(&rpdev->dev, "%s:%s",
 		     dev_name(dev->parent), rpdev->id.name);
 
-	rpdev->dev.parent = &vrp->vdev->dev;
 	rpdev->dev.bus = &rpmsg_bus;
 	rpdev->dev.release = rpmsg_release_device;
 
@@ -594,10 +607,9 @@ static struct rpmsg_device *rpmsg_create_channel(struct virtproc_info *vrp,
 	if (ret) {
 		dev_err(dev, "device_register failed: %d\n", ret);
 		put_device(&rpdev->dev);
-		return NULL;
 	}
 
-	return rpdev;
+	return ret;
 }
 
 /*
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 08/14] rpmsg: Split rpmsg core and virtio backend
  2016-08-16  0:17 ` Bjorn Andersson
@ 2016-08-16  0:17   ` Bjorn Andersson
  -1 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-16  0:17 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson
  Cc: linux-remoteproc, linux-arm-msm, linux-arm-kernel, linux-kernel,
	Sricharan R

Extract the generic rpmsg core functionality from the virtio rpmsg
implementation, splitting the implementation in a rpmsg core and a
virtio backend.

Based on initial work by Sricharan R <sricharan@codeaurora.org>

Cc: Sricharan R <sricharan@codeaurora.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/rpmsg/Kconfig            |   4 +
 drivers/rpmsg/Makefile           |   3 +-
 drivers/rpmsg/rpmsg_core.c       | 513 +++++++++++++++++++++++++++++++++++++++
 drivers/rpmsg/rpmsg_internal.h   |  45 ++++
 drivers/rpmsg/virtio_rpmsg_bus.c | 477 +-----------------------------------
 5 files changed, 569 insertions(+), 473 deletions(-)
 create mode 100644 drivers/rpmsg/rpmsg_core.c
 create mode 100644 drivers/rpmsg/rpmsg_internal.h

diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig
index 69a219387582..40614be88c97 100644
--- a/drivers/rpmsg/Kconfig
+++ b/drivers/rpmsg/Kconfig
@@ -3,6 +3,10 @@ menu "Rpmsg drivers"
 # RPMSG always gets selected by whoever wants it
 config RPMSG
 	tristate
+
+config RPMSG_VIRTIO
+	tristate
+	select RPMSG
 	select VIRTIO
 	select VIRTUALIZATION
 
diff --git a/drivers/rpmsg/Makefile b/drivers/rpmsg/Makefile
index 7617fcb8259f..383213417a00 100644
--- a/drivers/rpmsg/Makefile
+++ b/drivers/rpmsg/Makefile
@@ -1 +1,2 @@
-obj-$(CONFIG_RPMSG)	+= virtio_rpmsg_bus.o
+obj-$(CONFIG_RPMSG)	+= rpmsg_core.o
+obj-$(CONFIG_RPMSG_VIRTIO) += virtio_rpmsg_bus.o
diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
new file mode 100644
index 000000000000..73bbc5ea5778
--- /dev/null
+++ b/drivers/rpmsg/rpmsg_core.c
@@ -0,0 +1,513 @@
+/*
+ * Virtio-based remote processor messaging bus
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * Ohad Ben-Cohen <ohad@wizery.com>
+ * Brian Swetland <swetland@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/virtio.h>
+#include <linux/virtio_ids.h>
+#include <linux/virtio_config.h>
+#include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/idr.h>
+#include <linux/jiffies.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/rpmsg.h>
+#include <linux/mutex.h>
+#include <linux/of_device.h>
+
+#include "rpmsg_internal.h"
+
+/**
+ * rpmsg_create_ept() - create a new rpmsg_endpoint
+ * @rpdev: rpmsg channel device
+ * @cb: rx callback handler
+ * @priv: private data for the driver's use
+ * @addr: local rpmsg address to bind with @cb
+ *
+ * Every rpmsg address in the system is bound to an rx callback (so when
+ * inbound messages arrive, they are dispatched by the rpmsg bus using the
+ * appropriate callback handler) by means of an rpmsg_endpoint struct.
+ *
+ * This function allows drivers to create such an endpoint, and by that,
+ * bind a callback, and possibly some private data too, to an rpmsg address
+ * (either one that is known in advance, or one that will be dynamically
+ * assigned for them).
+ *
+ * Simple rpmsg drivers need not call rpmsg_create_ept, because an endpoint
+ * is already created for them when they are probed by the rpmsg bus
+ * (using the rx callback provided when they registered to the rpmsg bus).
+ *
+ * So things should just work for simple drivers: they already have an
+ * endpoint, their rx callback is bound to their rpmsg address, and when
+ * relevant inbound messages arrive (i.e. messages which their dst address
+ * equals to the src address of their rpmsg channel), the driver's handler
+ * is invoked to process it.
+ *
+ * That said, more complicated drivers might do need to allocate
+ * additional rpmsg addresses, and bind them to different rx callbacks.
+ * To accomplish that, those drivers need to call this function.
+ *
+ * Drivers should provide their @rpdev channel (so the new endpoint would belong
+ * to the same remote processor their channel belongs to), an rx callback
+ * function, an optional private data (which is provided back when the
+ * rx callback is invoked), and an address they want to bind with the
+ * callback. If @addr is RPMSG_ADDR_ANY, then rpmsg_create_ept will
+ * dynamically assign them an available rpmsg address (drivers should have
+ * a very good reason why not to always use RPMSG_ADDR_ANY here).
+ *
+ * Returns a pointer to the endpoint on success, or NULL on error.
+ */
+struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev,
+				rpmsg_rx_cb_t cb, void *priv, u32 addr)
+{
+	return rpdev->create_ept(rpdev, cb, priv, addr);
+}
+EXPORT_SYMBOL(rpmsg_create_ept);
+
+/**
+ * rpmsg_destroy_ept() - destroy an existing rpmsg endpoint
+ * @ept: endpoing to destroy
+ *
+ * Should be used by drivers to destroy an rpmsg endpoint previously
+ * created with rpmsg_create_ept().
+ */
+void rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
+{
+	ept->rpdev->destroy_ept(ept);
+}
+EXPORT_SYMBOL(rpmsg_destroy_ept);
+
+/**
+ * rpmsg_send() - send a message across to the remote processor
+ * @ept: the rpmsg endpoint
+ * @data: payload of message
+ * @len: length of payload
+ *
+ * This function sends @data of length @len on the @ept endpoint.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to, using @ept's address and its associated rpmsg
+ * device destination addresses.
+ * In case there are no TX buffers available, the function will block until
+ * one becomes available, or a timeout of 15 seconds elapses. When the latter
+ * happens, -ERESTARTSYS is returned.
+ *
+ * Can only be called from process context (for now).
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
+{
+	struct rpmsg_device *rpdev = ept->rpdev;
+
+	return rpdev->send(ept, data, len);
+}
+
+/**
+ * rpmsg_sendto() - send a message across to the remote processor, specify dst
+ * @ept: the rpmsg endpoint
+ * @data: payload of message
+ * @len: length of payload
+ * @dst: destination address
+ *
+ * This function sends @data of length @len to the remote @dst address.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to, using @ept's address as source.
+ * In case there are no TX buffers available, the function will block until
+ * one becomes available, or a timeout of 15 seconds elapses. When the latter
+ * happens, -ERESTARTSYS is returned.
+ *
+ * Can only be called from process context (for now).
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
+{
+	struct rpmsg_device *rpdev = ept->rpdev;
+
+	return rpdev->sendto(ept, data, len, dst);
+}
+EXPORT_SYMBOL(rpmsg_sendto);
+
+/**
+ * rpmsg_send_offchannel() - send a message using explicit src/dst addresses
+ * @ept: the rpmsg endpoint
+ * @src: source address
+ * @dst: destination address
+ * @data: payload of message
+ * @len: length of payload
+ *
+ * This function sends @data of length @len to the remote @dst address,
+ * and uses @src as the source address.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to.
+ * In case there are no TX buffers available, the function will block until
+ * one becomes available, or a timeout of 15 seconds elapses. When the latter
+ * happens, -ERESTARTSYS is returned.
+ *
+ * Can only be called from process context (for now).
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
+			  void *data, int len)
+{
+	struct rpmsg_device *rpdev = ept->rpdev;
+
+	return rpdev->send_offchannel(ept, src, dst, data, len);
+}
+EXPORT_SYMBOL(rpmsg_send_offchannel);
+
+/**
+ * rpmsg_send() - send a message across to the remote processor
+ * @ept: the rpmsg endpoint
+ * @data: payload of message
+ * @len: length of payload
+ *
+ * This function sends @data of length @len on the @ept endpoint.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to, using @ept's address as source and its associated
+ * rpdev's address as destination.
+ * In case there are no TX buffers available, the function will immediately
+ * return -ENOMEM without waiting until one becomes available.
+ *
+ * Can only be called from process context (for now).
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
+{
+	struct rpmsg_device *rpdev = ept->rpdev;
+
+	return rpdev->trysend(ept, data, len);
+}
+EXPORT_SYMBOL(rpmsg_trysend);
+
+/**
+ * rpmsg_sendto() - send a message across to the remote processor, specify dst
+ * @ept: the rpmsg endpoint
+ * @data: payload of message
+ * @len: length of payload
+ * @dst: destination address
+ *
+ * This function sends @data of length @len to the remote @dst address.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to, using @ept's address as source.
+ * In case there are no TX buffers available, the function will immediately
+ * return -ENOMEM without waiting until one becomes available.
+ *
+ * Can only be called from process context (for now).
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
+{
+	struct rpmsg_device *rpdev = ept->rpdev;
+
+	return rpdev->trysendto(ept, data, len, dst);
+}
+EXPORT_SYMBOL(rpmsg_trysendto);
+
+/**
+ * rpmsg_send_offchannel() - send a message using explicit src/dst addresses
+ * @ept: the rpmsg endpoint
+ * @src: source address
+ * @dst: destination address
+ * @data: payload of message
+ * @len: length of payload
+ *
+ * This function sends @data of length @len to the remote @dst address,
+ * and uses @src as the source address.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to.
+ * In case there are no TX buffers available, the function will immediately
+ * return -ENOMEM without waiting until one becomes available.
+ *
+ * Can only be called from process context (for now).
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
+			     void *data, int len)
+{
+	struct rpmsg_device *rpdev = ept->rpdev;
+
+	return rpdev->trysend_offchannel(ept, src, dst, data, len);
+}
+EXPORT_SYMBOL(rpmsg_trysend_offchannel);
+
+/* sysfs show configuration fields */
+#define rpmsg_show_attr(field, path, format_string)			\
+static ssize_t								\
+field##_show(struct device *dev,					\
+			struct device_attribute *attr, char *buf)	\
+{									\
+	struct rpmsg_device *rpdev = to_rpmsg_device(dev);		\
+									\
+	return sprintf(buf, format_string, rpdev->path);		\
+}
+
+/* for more info, see Documentation/ABI/testing/sysfs-bus-rpmsg */
+rpmsg_show_attr(name, id.name, "%s\n");
+rpmsg_show_attr(src, src, "0x%x\n");
+rpmsg_show_attr(dst, dst, "0x%x\n");
+rpmsg_show_attr(announce, announce ? "true" : "false", "%s\n");
+
+static ssize_t modalias_show(struct device *dev,
+			     struct device_attribute *attr, char *buf)
+{
+	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
+
+	return sprintf(buf, RPMSG_DEVICE_MODALIAS_FMT "\n", rpdev->id.name);
+}
+
+static struct device_attribute rpmsg_dev_attrs[] = {
+	__ATTR_RO(name),
+	__ATTR_RO(modalias),
+	__ATTR_RO(dst),
+	__ATTR_RO(src),
+	__ATTR_RO(announce),
+	__ATTR_NULL
+};
+
+/* rpmsg devices and drivers are matched using the service name */
+static inline int rpmsg_id_match(const struct rpmsg_device *rpdev,
+				  const struct rpmsg_device_id *id)
+{
+	return strncmp(id->name, rpdev->id.name, RPMSG_NAME_SIZE) == 0;
+}
+
+/* match rpmsg channel and rpmsg driver */
+static int rpmsg_dev_match(struct device *dev, struct device_driver *drv)
+{
+	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
+	struct rpmsg_driver *rpdrv = to_rpmsg_driver(drv);
+	const struct rpmsg_device_id *ids = rpdrv->id_table;
+	unsigned int i;
+
+	if (ids)
+		for (i = 0; ids[i].name[0]; i++)
+			if (rpmsg_id_match(rpdev, &ids[i]))
+				return 1;
+
+	return of_driver_match_device(dev, drv);
+}
+
+static int rpmsg_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
+
+	return add_uevent_var(env, "MODALIAS=" RPMSG_DEVICE_MODALIAS_FMT,
+					rpdev->id.name);
+}
+
+/*
+ * when an rpmsg driver is probed with a channel, we seamlessly create
+ * it an endpoint, binding its rx callback to a unique local rpmsg
+ * address.
+ *
+ * if we need to, we also announce about this channel to the remote
+ * processor (needed in case the driver is exposing an rpmsg service).
+ */
+static int rpmsg_dev_probe(struct device *dev)
+{
+	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
+	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
+	struct rpmsg_endpoint *ept;
+	int err;
+
+	ept = rpmsg_create_ept(rpdev, rpdrv->callback, NULL, rpdev->src);
+	if (!ept) {
+		dev_err(dev, "failed to create endpoint\n");
+		err = -ENOMEM;
+		goto out;
+	}
+
+	rpdev->ept = ept;
+	rpdev->src = ept->addr;
+
+	err = rpdrv->probe(rpdev);
+	if (err) {
+		dev_err(dev, "%s: failed: %d\n", __func__, err);
+		rpmsg_destroy_ept(ept);
+		goto out;
+	}
+
+	if (rpdev->announce_create)
+		err = rpdev->announce_create(rpdev);
+out:
+	return err;
+}
+
+static int rpmsg_dev_remove(struct device *dev)
+{
+	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
+	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
+	int err = 0;
+
+	if (rpdev->announce_destroy)
+		err = rpdev->announce_destroy(rpdev);
+
+	rpdrv->remove(rpdev);
+
+	rpmsg_destroy_ept(rpdev->ept);
+
+	return err;
+}
+
+static struct bus_type rpmsg_bus = {
+	.name		= "rpmsg",
+	.match		= rpmsg_dev_match,
+	.dev_attrs	= rpmsg_dev_attrs,
+	.uevent		= rpmsg_uevent,
+	.probe		= rpmsg_dev_probe,
+	.remove		= rpmsg_dev_remove,
+};
+
+static void rpmsg_release_device(struct device *dev)
+{
+	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
+
+	kfree(rpdev);
+}
+
+int rpmsg_register_device(struct rpmsg_device *rpdev)
+{
+	struct device *dev = &rpdev->dev;
+	int ret;
+
+	dev_set_name(&rpdev->dev, "%s:%s",
+		     dev_name(dev->parent), rpdev->id.name);
+
+	rpdev->dev.bus = &rpmsg_bus;
+	rpdev->dev.release = rpmsg_release_device;
+
+	ret = device_register(&rpdev->dev);
+	if (ret) {
+		dev_err(dev, "device_register failed: %d\n", ret);
+		put_device(&rpdev->dev);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(rpmsg_register_device);
+
+/*
+ * match an rpmsg channel with a channel info struct.
+ * this is used to make sure we're not creating rpmsg devices for channels
+ * that already exist.
+ */
+static int rpmsg_channel_match(struct device *dev, void *data)
+{
+	struct rpmsg_channel_info *chinfo = data;
+	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
+
+	if (chinfo->src != RPMSG_ADDR_ANY && chinfo->src != rpdev->src)
+		return 0;
+
+	if (chinfo->dst != RPMSG_ADDR_ANY && chinfo->dst != rpdev->dst)
+		return 0;
+
+	if (strncmp(chinfo->name, rpdev->id.name, RPMSG_NAME_SIZE))
+		return 0;
+
+	/* found a match ! */
+	return 1;
+}
+
+struct device *rpmsg_find_device(struct device *parent,
+				 struct rpmsg_channel_info *chinfo)
+{
+	return device_find_child(parent, chinfo, rpmsg_channel_match);
+
+}
+EXPORT_SYMBOL(rpmsg_find_device);
+
+/*
+ * find an existing channel using its name + address properties,
+ * and destroy it
+ */
+int rpmsg_unregister_device(struct device *parent,
+			    struct rpmsg_channel_info *chinfo)
+{
+	struct device *dev;
+
+	dev = rpmsg_find_device(parent, chinfo);
+	if (!dev)
+		return -EINVAL;
+
+	device_unregister(dev);
+
+	put_device(dev);
+
+	return 0;
+}
+EXPORT_SYMBOL(rpmsg_unregister_device);
+
+/**
+ * __register_rpmsg_driver() - register an rpmsg driver with the rpmsg bus
+ * @rpdrv: pointer to a struct rpmsg_driver
+ * @owner: owning module/driver
+ *
+ * Returns 0 on success, and an appropriate error value on failure.
+ */
+int __register_rpmsg_driver(struct rpmsg_driver *rpdrv, struct module *owner)
+{
+	rpdrv->drv.bus = &rpmsg_bus;
+	rpdrv->drv.owner = owner;
+	return driver_register(&rpdrv->drv);
+}
+EXPORT_SYMBOL(__register_rpmsg_driver);
+
+/**
+ * unregister_rpmsg_driver() - unregister an rpmsg driver from the rpmsg bus
+ * @rpdrv: pointer to a struct rpmsg_driver
+ *
+ * Returns 0 on success, and an appropriate error value on failure.
+ */
+void unregister_rpmsg_driver(struct rpmsg_driver *rpdrv)
+{
+	driver_unregister(&rpdrv->drv);
+}
+EXPORT_SYMBOL(unregister_rpmsg_driver);
+
+
+static int __init rpmsg_init(void)
+{
+	int ret;
+
+	ret = bus_register(&rpmsg_bus);
+	if (ret)
+		pr_err("failed to register rpmsg bus: %d\n", ret);
+
+	return ret;
+}
+postcore_initcall(rpmsg_init);
+
+static void __exit rpmsg_fini(void)
+{
+	bus_unregister(&rpmsg_bus);
+}
+module_exit(rpmsg_fini);
+
+MODULE_DESCRIPTION("remote processor messaging bus");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/rpmsg/rpmsg_internal.h b/drivers/rpmsg/rpmsg_internal.h
new file mode 100644
index 000000000000..fa91075c7956
--- /dev/null
+++ b/drivers/rpmsg/rpmsg_internal.h
@@ -0,0 +1,45 @@
+/*
+ * Virtio-based remote processor messaging bus
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * Ohad Ben-Cohen <ohad@wizery.com>
+ * Brian Swetland <swetland@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __RPMSG_INTERNAL_H__
+#define __RPMSG_INTERNAL_H__
+
+#define to_rpmsg_device(d) container_of(d, struct rpmsg_device, dev)
+#define to_rpmsg_driver(d) container_of(d, struct rpmsg_driver, drv)
+
+/**
+ * struct rpmsg_channel_info - internal channel info representation
+ * @name: name of service
+ * @src: local address
+ * @dst: destination address
+ */
+struct rpmsg_channel_info {
+	char name[RPMSG_NAME_SIZE];
+	u32 src;
+	u32 dst;
+};
+
+int rpmsg_register_device(struct rpmsg_device *rpdev);
+int rpmsg_unregister_device(struct device *parent,
+			    struct rpmsg_channel_info *chinfo);
+
+struct device *rpmsg_find_device(struct device *parent,
+				 struct rpmsg_channel_info *chinfo);
+
+#endif
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 5cadb75a225d..779c54304774 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -35,6 +35,8 @@
 #include <linux/mutex.h>
 #include <linux/of_device.h>
 
+#include "rpmsg_internal.h"
+
 /**
  * struct virtproc_info - virtual remote processor state
  * @vdev:	the virtio device
@@ -73,21 +75,6 @@ struct virtproc_info {
 	struct rpmsg_endpoint *ns_ept;
 };
 
-/**
- * struct rpmsg_channel_info - internal channel info representation
- * @name: name of service
- * @src: local address
- * @dst: destination address
- */
-struct rpmsg_channel_info {
-	char name[RPMSG_NAME_SIZE];
-	u32 src;
-	u32 dst;
-};
-
-#define to_rpmsg_device(d) container_of(d, struct rpmsg_device, dev)
-#define to_rpmsg_driver(d) container_of(d, struct rpmsg_driver, drv)
-
 /*
  * We're allocating buffers of 512 bytes each for communications. The
  * number of buffers will be computed from the number of buffers supported
@@ -129,72 +116,6 @@ static int virtio_rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data,
 				  int len, u32 dst);
 static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src,
 					   u32 dst, void *data, int len);
-static int rpmsg_register_device(struct rpmsg_device *rpdev);
-
-/* sysfs show configuration fields */
-#define rpmsg_show_attr(field, path, format_string)			\
-static ssize_t								\
-field##_show(struct device *dev,					\
-			struct device_attribute *attr, char *buf)	\
-{									\
-	struct rpmsg_device *rpdev = to_rpmsg_device(dev);		\
-									\
-	return sprintf(buf, format_string, rpdev->path);		\
-}
-
-/* for more info, see Documentation/ABI/testing/sysfs-bus-rpmsg */
-rpmsg_show_attr(name, id.name, "%s\n");
-rpmsg_show_attr(src, src, "0x%x\n");
-rpmsg_show_attr(dst, dst, "0x%x\n");
-rpmsg_show_attr(announce, announce ? "true" : "false", "%s\n");
-
-static ssize_t modalias_show(struct device *dev,
-			     struct device_attribute *attr, char *buf)
-{
-	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
-
-	return sprintf(buf, RPMSG_DEVICE_MODALIAS_FMT "\n", rpdev->id.name);
-}
-
-static struct device_attribute rpmsg_dev_attrs[] = {
-	__ATTR_RO(name),
-	__ATTR_RO(modalias),
-	__ATTR_RO(dst),
-	__ATTR_RO(src),
-	__ATTR_RO(announce),
-	__ATTR_NULL
-};
-
-/* rpmsg devices and drivers are matched using the service name */
-static inline int rpmsg_id_match(const struct rpmsg_device *rpdev,
-				 const struct rpmsg_device_id *id)
-{
-	return strncmp(id->name, rpdev->id.name, RPMSG_NAME_SIZE) == 0;
-}
-
-/* match rpmsg channel and rpmsg driver */
-static int rpmsg_dev_match(struct device *dev, struct device_driver *drv)
-{
-	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
-	struct rpmsg_driver *rpdrv = to_rpmsg_driver(drv);
-	const struct rpmsg_device_id *ids = rpdrv->id_table;
-	unsigned int i;
-
-	if (ids)
-		for (i = 0; ids[i].name[0]; i++)
-			if (rpmsg_id_match(rpdev, &ids[i]))
-				return 1;
-
-	return of_driver_match_device(dev, drv);
-}
-
-static int rpmsg_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
-	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
-
-	return add_uevent_var(env, "MODALIAS=" RPMSG_DEVICE_MODALIAS_FMT,
-					rpdev->id.name);
-}
 
 /**
  * __ept_release() - deallocate an rpmsg endpoint
@@ -266,53 +187,6 @@ free_ept:
 	return NULL;
 }
 
-/**
- * rpmsg_create_ept() - create a new rpmsg_endpoint
- * @rpdev: rpmsg channel device
- * @cb: rx callback handler
- * @priv: private data for the driver's use
- * @addr: local rpmsg address to bind with @cb
- *
- * Every rpmsg address in the system is bound to an rx callback (so when
- * inbound messages arrive, they are dispatched by the rpmsg bus using the
- * appropriate callback handler) by means of an rpmsg_endpoint struct.
- *
- * This function allows drivers to create such an endpoint, and by that,
- * bind a callback, and possibly some private data too, to an rpmsg address
- * (either one that is known in advance, or one that will be dynamically
- * assigned for them).
- *
- * Simple rpmsg drivers need not call rpmsg_create_ept, because an endpoint
- * is already created for them when they are probed by the rpmsg bus
- * (using the rx callback provided when they registered to the rpmsg bus).
- *
- * So things should just work for simple drivers: they already have an
- * endpoint, their rx callback is bound to their rpmsg address, and when
- * relevant inbound messages arrive (i.e. messages which their dst address
- * equals to the src address of their rpmsg channel), the driver's handler
- * is invoked to process it.
- *
- * That said, more complicated drivers might do need to allocate
- * additional rpmsg addresses, and bind them to different rx callbacks.
- * To accomplish that, those drivers need to call this function.
- *
- * Drivers should provide their @rpdev channel (so the new endpoint would belong
- * to the same remote processor their channel belongs to), an rx callback
- * function, an optional private data (which is provided back when the
- * rx callback is invoked), and an address they want to bind with the
- * callback. If @addr is RPMSG_ADDR_ANY, then rpmsg_create_ept will
- * dynamically assign them an available rpmsg address (drivers should have
- * a very good reason why not to always use RPMSG_ADDR_ANY here).
- *
- * Returns a pointer to the endpoint on success, or NULL on error.
- */
-struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev,
-					rpmsg_rx_cb_t cb, void *priv, u32 addr)
-{
-	return rpdev->create_ept(rpdev, cb, priv, addr);
-}
-EXPORT_SYMBOL(rpmsg_create_ept);
-
 static struct rpmsg_endpoint *virtio_rpmsg_create_ept(struct rpmsg_device *rpdev,
 						      rpmsg_rx_cb_t cb,
 						      void *priv, u32 addr)
@@ -346,62 +220,11 @@ __rpmsg_destroy_ept(struct virtproc_info *vrp, struct rpmsg_endpoint *ept)
 	kref_put(&ept->refcount, __ept_release);
 }
 
-/**
- * rpmsg_destroy_ept() - destroy an existing rpmsg endpoint
- * @ept: endpoing to destroy
- *
- * Should be used by drivers to destroy an rpmsg endpoint previously
- * created with rpmsg_create_ept().
- */
-void rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
-{
-	ept->rpdev->destroy_ept(ept);
-}
-EXPORT_SYMBOL(rpmsg_destroy_ept);
-
 static void virtio_rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
 {
 	__rpmsg_destroy_ept(ept->rpdev->vrp, ept);
 }
 
-/*
- * when an rpmsg driver is probed with a channel, we seamlessly create
- * it an endpoint, binding its rx callback to a unique local rpmsg
- * address.
- *
- * if we need to, we also announce about this channel to the remote
- * processor (needed in case the driver is exposing an rpmsg service).
- */
-static int rpmsg_dev_probe(struct device *dev)
-{
-	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
-	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
-	struct rpmsg_endpoint *ept;
-	int err;
-
-	ept = rpmsg_create_ept(rpdev, rpdrv->callback, NULL, rpdev->src);
-	if (!ept) {
-		dev_err(dev, "failed to create endpoint\n");
-		err = -ENOMEM;
-		goto out;
-	}
-
-	rpdev->ept = ept;
-	rpdev->src = ept->addr;
-
-	err = rpdrv->probe(rpdev);
-	if (err) {
-		dev_err(dev, "%s: failed: %d\n", __func__, err);
-		rpmsg_destroy_ept(ept);
-		goto out;
-	}
-
-	if (rpdev->announce_create)
-		err = rpdev->announce_create(rpdev);
-out:
-	return err;
-}
-
 static int virtio_rpmsg_announce_create(struct rpmsg_device *rpdev)
 {
 	struct virtproc_info *vrp = rpdev->vrp;
@@ -448,88 +271,6 @@ static int virtio_rpmsg_announce_destroy(struct rpmsg_device *rpdev)
 	return err;
 }
 
-static int rpmsg_dev_remove(struct device *dev)
-{
-	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
-	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
-	int err = 0;
-
-	if (rpdev->announce_destroy)
-		err = rpdev->announce_destroy(rpdev);
-
-	rpdrv->remove(rpdev);
-
-	rpmsg_destroy_ept(rpdev->ept);
-
-	return err;
-}
-
-static struct bus_type rpmsg_bus = {
-	.name		= "rpmsg",
-	.match		= rpmsg_dev_match,
-	.dev_attrs	= rpmsg_dev_attrs,
-	.uevent		= rpmsg_uevent,
-	.probe		= rpmsg_dev_probe,
-	.remove		= rpmsg_dev_remove,
-};
-
-/**
- * __register_rpmsg_driver() - register an rpmsg driver with the rpmsg bus
- * @rpdrv: pointer to a struct rpmsg_driver
- * @owner: owning module/driver
- *
- * Returns 0 on success, and an appropriate error value on failure.
- */
-int __register_rpmsg_driver(struct rpmsg_driver *rpdrv, struct module *owner)
-{
-	rpdrv->drv.bus = &rpmsg_bus;
-	rpdrv->drv.owner = owner;
-	return driver_register(&rpdrv->drv);
-}
-EXPORT_SYMBOL(__register_rpmsg_driver);
-
-/**
- * unregister_rpmsg_driver() - unregister an rpmsg driver from the rpmsg bus
- * @rpdrv: pointer to a struct rpmsg_driver
- *
- * Returns 0 on success, and an appropriate error value on failure.
- */
-void unregister_rpmsg_driver(struct rpmsg_driver *rpdrv)
-{
-	driver_unregister(&rpdrv->drv);
-}
-EXPORT_SYMBOL(unregister_rpmsg_driver);
-
-static void rpmsg_release_device(struct device *dev)
-{
-	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
-
-	kfree(rpdev);
-}
-
-/*
- * match an rpmsg channel with a channel info struct.
- * this is used to make sure we're not creating rpmsg devices for channels
- * that already exist.
- */
-static int rpmsg_device_match(struct device *dev, void *data)
-{
-	struct rpmsg_channel_info *chinfo = data;
-	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
-
-	if (chinfo->src != RPMSG_ADDR_ANY && chinfo->src != rpdev->src)
-		return 0;
-
-	if (chinfo->dst != RPMSG_ADDR_ANY && chinfo->dst != rpdev->dst)
-		return 0;
-
-	if (strncmp(chinfo->name, rpdev->id.name, RPMSG_NAME_SIZE))
-		return 0;
-
-	/* found a match ! */
-	return 1;
-}
-
 static const struct rpmsg_device virtio_rpmsg_ops = {
 	.create_ept = virtio_rpmsg_create_ept,
 	.destroy_ept = virtio_rpmsg_destroy_ept,
@@ -556,7 +297,7 @@ static struct rpmsg_device *rpmsg_create_channel(struct virtproc_info *vrp,
 	int ret;
 
 	/* make sure a similar channel doesn't already exist */
-	tmp = device_find_child(dev, chinfo, rpmsg_device_match);
+	tmp = rpmsg_find_device(dev, chinfo);
 	if (tmp) {
 		/* decrement the matched device's refcount back */
 		put_device(tmp);
@@ -592,47 +333,6 @@ static struct rpmsg_device *rpmsg_create_channel(struct virtproc_info *vrp,
 	return rpdev;
 }
 
-static int rpmsg_register_device(struct rpmsg_device *rpdev)
-{
-	struct device *dev = &rpdev->dev;
-	int ret;
-
-	dev_set_name(&rpdev->dev, "%s:%s",
-		     dev_name(dev->parent), rpdev->id.name);
-
-	rpdev->dev.bus = &rpmsg_bus;
-	rpdev->dev.release = rpmsg_release_device;
-
-	ret = device_register(&rpdev->dev);
-	if (ret) {
-		dev_err(dev, "device_register failed: %d\n", ret);
-		put_device(&rpdev->dev);
-	}
-
-	return ret;
-}
-
-/*
- * find an existing channel using its name + address properties,
- * and destroy it
- */
-static int rpmsg_destroy_channel(struct virtproc_info *vrp,
-				 struct rpmsg_channel_info *chinfo)
-{
-	struct virtio_device *vdev = vrp->vdev;
-	struct device *dev;
-
-	dev = device_find_child(&vdev->dev, chinfo, rpmsg_device_match);
-	if (!dev)
-		return -EINVAL;
-
-	device_unregister(dev);
-
-	put_device(dev);
-
-	return 0;
-}
-
 /* super simple buffer "allocator" that is just enough for now */
 static void *get_a_tx_buf(struct virtproc_info *vrp)
 {
@@ -844,31 +544,6 @@ out:
 	return err;
 }
 
-/**
- * rpmsg_send() - send a message across to the remote processor
- * @ept: the rpmsg endpoint
- * @data: payload of message
- * @len: length of payload
- *
- * This function sends @data of length @len on the @ept endpoint.
- * The message will be sent to the remote processor which the @ept
- * endpoint belongs to, using @ept's address and its associated rpmsg
- * device destination addresses.
- * In case there are no TX buffers available, the function will block until
- * one becomes available, or a timeout of 15 seconds elapses. When the latter
- * happens, -ERESTARTSYS is returned.
- *
- * Can only be called from process context (for now).
- *
- * Returns 0 on success and an appropriate error value on failure.
- */
-int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
-{
-	struct rpmsg_device *rpdev = ept->rpdev;
-
-	return rpdev->send(ept, data, len);
-}
-
 static int virtio_rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
 {
 	struct rpmsg_device *rpdev = ept->rpdev;
@@ -877,32 +552,6 @@ static int virtio_rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
 }
 
-/**
- * rpmsg_sendto() - send a message across to the remote processor, specify dst
- * @ept: the rpmsg endpoint
- * @data: payload of message
- * @len: length of payload
- * @dst: destination address
- *
- * This function sends @data of length @len to the remote @dst address.
- * The message will be sent to the remote processor which the @ept
- * endpoint belongs to, using @ept's address as source.
- * In case there are no TX buffers available, the function will block until
- * one becomes available, or a timeout of 15 seconds elapses. When the latter
- * happens, -ERESTARTSYS is returned.
- *
- * Can only be called from process context (for now).
- *
- * Returns 0 on success and an appropriate error value on failure.
- */
-int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
-{
-	struct rpmsg_device *rpdev = ept->rpdev;
-
-	return rpdev->sendto(ept, data, len, dst);
-}
-EXPORT_SYMBOL(rpmsg_sendto);
-
 static int virtio_rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len,
 			       u32 dst)
 {
@@ -912,35 +561,6 @@ static int virtio_rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len,
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
 }
 
-/**
- * rpmsg_send_offchannel() - send a message using explicit src/dst addresses
- * @ept: the rpmsg endpoint
- * @src: source address
- * @dst: destination address
- * @data: payload of message
- * @len: length of payload
- *
- * This function sends @data of length @len to the remote @dst address,
- * and uses @src as the source address.
- * The message will be sent to the remote processor which the @ept
- * endpoint belongs to.
- * In case there are no TX buffers available, the function will block until
- * one becomes available, or a timeout of 15 seconds elapses. When the latter
- * happens, -ERESTARTSYS is returned.
- *
- * Can only be called from process context (for now).
- *
- * Returns 0 on success and an appropriate error value on failure.
- */
-int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
-			  void *data, int len)
-{
-	struct rpmsg_device *rpdev = ept->rpdev;
-
-	return rpdev->send_offchannel(ept, src, dst, data, len);
-}
-EXPORT_SYMBOL(rpmsg_send_offchannel);
-
 static int virtio_rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src,
 					u32 dst, void *data, int len)
 {
@@ -949,31 +569,6 @@ static int virtio_rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src,
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
 }
 
-/**
- * rpmsg_send() - send a message across to the remote processor
- * @ept: the rpmsg endpoint
- * @data: payload of message
- * @len: length of payload
- *
- * This function sends @data of length @len on the @ept endpoint.
- * The message will be sent to the remote processor which the @ept
- * endpoint belongs to, using @ept's addres as source and its associated
- * rpdev's address as destination.
- * In case there are no TX buffers available, the function will immediately
- * return -ENOMEM without waiting until one becomes available.
- *
- * Can only be called from process context (for now).
- *
- * Returns 0 on success and an appropriate error value on failure.
- */
-int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
-{
-	struct rpmsg_device *rpdev = ept->rpdev;
-
-	return rpdev->trysend(ept, data, len);
-}
-EXPORT_SYMBOL(rpmsg_trysend);
-
 static int virtio_rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
 {
 	struct rpmsg_device *rpdev = ept->rpdev;
@@ -982,31 +577,6 @@ static int virtio_rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
 }
 
-/**
- * rpmsg_sendto() - send a message across to the remote processor, specify dst
- * @ept: the rpmsg endpoint
- * @data: payload of message
- * @len: length of payload
- * @dst: destination address
- *
- * This function sends @data of length @len to the remote @dst address.
- * The message will be sent to the remote processor which the @ept
- * endpoint belongs to, using @ept's address as source.
- * In case there are no TX buffers available, the function will immediately
- * return -ENOMEM without waiting until one becomes available.
- *
- * Can only be called from process context (for now).
- *
- * Returns 0 on success and an appropriate error value on failure.
- */
-int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
-{
-	struct rpmsg_device *rpdev = ept->rpdev;
-
-	return rpdev->trysendto(ept, data, len, dst);
-}
-EXPORT_SYMBOL(rpmsg_trysendto);
-
 static int virtio_rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data,
 				  int len, u32 dst)
 {
@@ -1016,34 +586,6 @@ static int virtio_rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data,
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
 }
 
-/**
- * rpmsg_send_offchannel() - send a message using explicit src/dst addresses
- * @ept: the rpmsg endpoint
- * @src: source address
- * @dst: destination address
- * @data: payload of message
- * @len: length of payload
- *
- * This function sends @data of length @len to the remote @dst address,
- * and uses @src as the source address.
- * The message will be sent to the remote processor which the @ept
- * endpoint belongs to.
- * In case there are no TX buffers available, the function will immediately
- * return -ENOMEM without waiting until one becomes available.
- *
- * Can only be called from process context (for now).
- *
- * Returns 0 on success and an appropriate error value on failure.
- */
-int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
-			     void *data, int len)
-{
-	struct rpmsg_device *rpdev = ept->rpdev;
-
-	return rpdev->trysend_offchannel(ept, src, dst, data, len);
-}
-EXPORT_SYMBOL(rpmsg_trysend_offchannel);
-
 static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src,
 					   u32 dst, void *data, int len)
 {
@@ -1208,7 +750,7 @@ static void rpmsg_ns_cb(struct rpmsg_device *rpdev, void *data, int len,
 	chinfo.dst = msg->addr;
 
 	if (msg->flags & RPMSG_NS_DESTROY) {
-		ret = rpmsg_destroy_channel(vrp, &chinfo);
+		ret = rpmsg_unregister_device(&vrp->vdev->dev, &chinfo);
 		if (ret)
 			dev_err(dev, "rpmsg_destroy_channel failed: %d\n", ret);
 	} else {
@@ -1393,17 +935,9 @@ static int __init rpmsg_init(void)
 {
 	int ret;
 
-	ret = bus_register(&rpmsg_bus);
-	if (ret) {
-		pr_err("failed to register rpmsg bus: %d\n", ret);
-		return ret;
-	}
-
 	ret = register_virtio_driver(&virtio_ipc_driver);
-	if (ret) {
+	if (ret)
 		pr_err("failed to register virtio driver: %d\n", ret);
-		bus_unregister(&rpmsg_bus);
-	}
 
 	return ret;
 }
@@ -1412,7 +946,6 @@ subsys_initcall(rpmsg_init);
 static void __exit rpmsg_fini(void)
 {
 	unregister_virtio_driver(&virtio_ipc_driver);
-	bus_unregister(&rpmsg_bus);
 }
 module_exit(rpmsg_fini);
 
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 08/14] rpmsg: Split rpmsg core and virtio backend
@ 2016-08-16  0:17   ` Bjorn Andersson
  0 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-16  0:17 UTC (permalink / raw)
  To: linux-arm-kernel

Extract the generic rpmsg core functionality from the virtio rpmsg
implementation, splitting the implementation in a rpmsg core and a
virtio backend.

Based on initial work by Sricharan R <sricharan@codeaurora.org>

Cc: Sricharan R <sricharan@codeaurora.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/rpmsg/Kconfig            |   4 +
 drivers/rpmsg/Makefile           |   3 +-
 drivers/rpmsg/rpmsg_core.c       | 513 +++++++++++++++++++++++++++++++++++++++
 drivers/rpmsg/rpmsg_internal.h   |  45 ++++
 drivers/rpmsg/virtio_rpmsg_bus.c | 477 +-----------------------------------
 5 files changed, 569 insertions(+), 473 deletions(-)
 create mode 100644 drivers/rpmsg/rpmsg_core.c
 create mode 100644 drivers/rpmsg/rpmsg_internal.h

diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig
index 69a219387582..40614be88c97 100644
--- a/drivers/rpmsg/Kconfig
+++ b/drivers/rpmsg/Kconfig
@@ -3,6 +3,10 @@ menu "Rpmsg drivers"
 # RPMSG always gets selected by whoever wants it
 config RPMSG
 	tristate
+
+config RPMSG_VIRTIO
+	tristate
+	select RPMSG
 	select VIRTIO
 	select VIRTUALIZATION
 
diff --git a/drivers/rpmsg/Makefile b/drivers/rpmsg/Makefile
index 7617fcb8259f..383213417a00 100644
--- a/drivers/rpmsg/Makefile
+++ b/drivers/rpmsg/Makefile
@@ -1 +1,2 @@
-obj-$(CONFIG_RPMSG)	+= virtio_rpmsg_bus.o
+obj-$(CONFIG_RPMSG)	+= rpmsg_core.o
+obj-$(CONFIG_RPMSG_VIRTIO) += virtio_rpmsg_bus.o
diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
new file mode 100644
index 000000000000..73bbc5ea5778
--- /dev/null
+++ b/drivers/rpmsg/rpmsg_core.c
@@ -0,0 +1,513 @@
+/*
+ * Virtio-based remote processor messaging bus
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * Ohad Ben-Cohen <ohad@wizery.com>
+ * Brian Swetland <swetland@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/virtio.h>
+#include <linux/virtio_ids.h>
+#include <linux/virtio_config.h>
+#include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/idr.h>
+#include <linux/jiffies.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/rpmsg.h>
+#include <linux/mutex.h>
+#include <linux/of_device.h>
+
+#include "rpmsg_internal.h"
+
+/**
+ * rpmsg_create_ept() - create a new rpmsg_endpoint
+ * @rpdev: rpmsg channel device
+ * @cb: rx callback handler
+ * @priv: private data for the driver's use
+ * @addr: local rpmsg address to bind with @cb
+ *
+ * Every rpmsg address in the system is bound to an rx callback (so when
+ * inbound messages arrive, they are dispatched by the rpmsg bus using the
+ * appropriate callback handler) by means of an rpmsg_endpoint struct.
+ *
+ * This function allows drivers to create such an endpoint, and by that,
+ * bind a callback, and possibly some private data too, to an rpmsg address
+ * (either one that is known in advance, or one that will be dynamically
+ * assigned for them).
+ *
+ * Simple rpmsg drivers need not call rpmsg_create_ept, because an endpoint
+ * is already created for them when they are probed by the rpmsg bus
+ * (using the rx callback provided when they registered to the rpmsg bus).
+ *
+ * So things should just work for simple drivers: they already have an
+ * endpoint, their rx callback is bound to their rpmsg address, and when
+ * relevant inbound messages arrive (i.e. messages which their dst address
+ * equals to the src address of their rpmsg channel), the driver's handler
+ * is invoked to process it.
+ *
+ * That said, more complicated drivers might do need to allocate
+ * additional rpmsg addresses, and bind them to different rx callbacks.
+ * To accomplish that, those drivers need to call this function.
+ *
+ * Drivers should provide their @rpdev channel (so the new endpoint would belong
+ * to the same remote processor their channel belongs to), an rx callback
+ * function, an optional private data (which is provided back when the
+ * rx callback is invoked), and an address they want to bind with the
+ * callback. If @addr is RPMSG_ADDR_ANY, then rpmsg_create_ept will
+ * dynamically assign them an available rpmsg address (drivers should have
+ * a very good reason why not to always use RPMSG_ADDR_ANY here).
+ *
+ * Returns a pointer to the endpoint on success, or NULL on error.
+ */
+struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev,
+				rpmsg_rx_cb_t cb, void *priv, u32 addr)
+{
+	return rpdev->create_ept(rpdev, cb, priv, addr);
+}
+EXPORT_SYMBOL(rpmsg_create_ept);
+
+/**
+ * rpmsg_destroy_ept() - destroy an existing rpmsg endpoint
+ * @ept: endpoing to destroy
+ *
+ * Should be used by drivers to destroy an rpmsg endpoint previously
+ * created with rpmsg_create_ept().
+ */
+void rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
+{
+	ept->rpdev->destroy_ept(ept);
+}
+EXPORT_SYMBOL(rpmsg_destroy_ept);
+
+/**
+ * rpmsg_send() - send a message across to the remote processor
+ * @ept: the rpmsg endpoint
+ * @data: payload of message
+ * @len: length of payload
+ *
+ * This function sends @data of length @len on the @ept endpoint.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to, using @ept's address and its associated rpmsg
+ * device destination addresses.
+ * In case there are no TX buffers available, the function will block until
+ * one becomes available, or a timeout of 15 seconds elapses. When the latter
+ * happens, -ERESTARTSYS is returned.
+ *
+ * Can only be called from process context (for now).
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
+{
+	struct rpmsg_device *rpdev = ept->rpdev;
+
+	return rpdev->send(ept, data, len);
+}
+
+/**
+ * rpmsg_sendto() - send a message across to the remote processor, specify dst
+ * @ept: the rpmsg endpoint
+ * @data: payload of message
+ * @len: length of payload
+ * @dst: destination address
+ *
+ * This function sends @data of length @len to the remote @dst address.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to, using @ept's address as source.
+ * In case there are no TX buffers available, the function will block until
+ * one becomes available, or a timeout of 15 seconds elapses. When the latter
+ * happens, -ERESTARTSYS is returned.
+ *
+ * Can only be called from process context (for now).
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
+{
+	struct rpmsg_device *rpdev = ept->rpdev;
+
+	return rpdev->sendto(ept, data, len, dst);
+}
+EXPORT_SYMBOL(rpmsg_sendto);
+
+/**
+ * rpmsg_send_offchannel() - send a message using explicit src/dst addresses
+ * @ept: the rpmsg endpoint
+ * @src: source address
+ * @dst: destination address
+ * @data: payload of message
+ * @len: length of payload
+ *
+ * This function sends @data of length @len to the remote @dst address,
+ * and uses @src as the source address.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to.
+ * In case there are no TX buffers available, the function will block until
+ * one becomes available, or a timeout of 15 seconds elapses. When the latter
+ * happens, -ERESTARTSYS is returned.
+ *
+ * Can only be called from process context (for now).
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
+			  void *data, int len)
+{
+	struct rpmsg_device *rpdev = ept->rpdev;
+
+	return rpdev->send_offchannel(ept, src, dst, data, len);
+}
+EXPORT_SYMBOL(rpmsg_send_offchannel);
+
+/**
+ * rpmsg_send() - send a message across to the remote processor
+ * @ept: the rpmsg endpoint
+ * @data: payload of message
+ * @len: length of payload
+ *
+ * This function sends @data of length @len on the @ept endpoint.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to, using @ept's address as source and its associated
+ * rpdev's address as destination.
+ * In case there are no TX buffers available, the function will immediately
+ * return -ENOMEM without waiting until one becomes available.
+ *
+ * Can only be called from process context (for now).
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
+{
+	struct rpmsg_device *rpdev = ept->rpdev;
+
+	return rpdev->trysend(ept, data, len);
+}
+EXPORT_SYMBOL(rpmsg_trysend);
+
+/**
+ * rpmsg_sendto() - send a message across to the remote processor, specify dst
+ * @ept: the rpmsg endpoint
+ * @data: payload of message
+ * @len: length of payload
+ * @dst: destination address
+ *
+ * This function sends @data of length @len to the remote @dst address.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to, using @ept's address as source.
+ * In case there are no TX buffers available, the function will immediately
+ * return -ENOMEM without waiting until one becomes available.
+ *
+ * Can only be called from process context (for now).
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
+{
+	struct rpmsg_device *rpdev = ept->rpdev;
+
+	return rpdev->trysendto(ept, data, len, dst);
+}
+EXPORT_SYMBOL(rpmsg_trysendto);
+
+/**
+ * rpmsg_send_offchannel() - send a message using explicit src/dst addresses
+ * @ept: the rpmsg endpoint
+ * @src: source address
+ * @dst: destination address
+ * @data: payload of message
+ * @len: length of payload
+ *
+ * This function sends @data of length @len to the remote @dst address,
+ * and uses @src as the source address.
+ * The message will be sent to the remote processor which the @ept
+ * endpoint belongs to.
+ * In case there are no TX buffers available, the function will immediately
+ * return -ENOMEM without waiting until one becomes available.
+ *
+ * Can only be called from process context (for now).
+ *
+ * Returns 0 on success and an appropriate error value on failure.
+ */
+int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
+			     void *data, int len)
+{
+	struct rpmsg_device *rpdev = ept->rpdev;
+
+	return rpdev->trysend_offchannel(ept, src, dst, data, len);
+}
+EXPORT_SYMBOL(rpmsg_trysend_offchannel);
+
+/* sysfs show configuration fields */
+#define rpmsg_show_attr(field, path, format_string)			\
+static ssize_t								\
+field##_show(struct device *dev,					\
+			struct device_attribute *attr, char *buf)	\
+{									\
+	struct rpmsg_device *rpdev = to_rpmsg_device(dev);		\
+									\
+	return sprintf(buf, format_string, rpdev->path);		\
+}
+
+/* for more info, see Documentation/ABI/testing/sysfs-bus-rpmsg */
+rpmsg_show_attr(name, id.name, "%s\n");
+rpmsg_show_attr(src, src, "0x%x\n");
+rpmsg_show_attr(dst, dst, "0x%x\n");
+rpmsg_show_attr(announce, announce ? "true" : "false", "%s\n");
+
+static ssize_t modalias_show(struct device *dev,
+			     struct device_attribute *attr, char *buf)
+{
+	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
+
+	return sprintf(buf, RPMSG_DEVICE_MODALIAS_FMT "\n", rpdev->id.name);
+}
+
+static struct device_attribute rpmsg_dev_attrs[] = {
+	__ATTR_RO(name),
+	__ATTR_RO(modalias),
+	__ATTR_RO(dst),
+	__ATTR_RO(src),
+	__ATTR_RO(announce),
+	__ATTR_NULL
+};
+
+/* rpmsg devices and drivers are matched using the service name */
+static inline int rpmsg_id_match(const struct rpmsg_device *rpdev,
+				  const struct rpmsg_device_id *id)
+{
+	return strncmp(id->name, rpdev->id.name, RPMSG_NAME_SIZE) == 0;
+}
+
+/* match rpmsg channel and rpmsg driver */
+static int rpmsg_dev_match(struct device *dev, struct device_driver *drv)
+{
+	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
+	struct rpmsg_driver *rpdrv = to_rpmsg_driver(drv);
+	const struct rpmsg_device_id *ids = rpdrv->id_table;
+	unsigned int i;
+
+	if (ids)
+		for (i = 0; ids[i].name[0]; i++)
+			if (rpmsg_id_match(rpdev, &ids[i]))
+				return 1;
+
+	return of_driver_match_device(dev, drv);
+}
+
+static int rpmsg_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
+
+	return add_uevent_var(env, "MODALIAS=" RPMSG_DEVICE_MODALIAS_FMT,
+					rpdev->id.name);
+}
+
+/*
+ * when an rpmsg driver is probed with a channel, we seamlessly create
+ * it an endpoint, binding its rx callback to a unique local rpmsg
+ * address.
+ *
+ * if we need to, we also announce about this channel to the remote
+ * processor (needed in case the driver is exposing an rpmsg service).
+ */
+static int rpmsg_dev_probe(struct device *dev)
+{
+	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
+	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
+	struct rpmsg_endpoint *ept;
+	int err;
+
+	ept = rpmsg_create_ept(rpdev, rpdrv->callback, NULL, rpdev->src);
+	if (!ept) {
+		dev_err(dev, "failed to create endpoint\n");
+		err = -ENOMEM;
+		goto out;
+	}
+
+	rpdev->ept = ept;
+	rpdev->src = ept->addr;
+
+	err = rpdrv->probe(rpdev);
+	if (err) {
+		dev_err(dev, "%s: failed: %d\n", __func__, err);
+		rpmsg_destroy_ept(ept);
+		goto out;
+	}
+
+	if (rpdev->announce_create)
+		err = rpdev->announce_create(rpdev);
+out:
+	return err;
+}
+
+static int rpmsg_dev_remove(struct device *dev)
+{
+	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
+	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
+	int err = 0;
+
+	if (rpdev->announce_destroy)
+		err = rpdev->announce_destroy(rpdev);
+
+	rpdrv->remove(rpdev);
+
+	rpmsg_destroy_ept(rpdev->ept);
+
+	return err;
+}
+
+static struct bus_type rpmsg_bus = {
+	.name		= "rpmsg",
+	.match		= rpmsg_dev_match,
+	.dev_attrs	= rpmsg_dev_attrs,
+	.uevent		= rpmsg_uevent,
+	.probe		= rpmsg_dev_probe,
+	.remove		= rpmsg_dev_remove,
+};
+
+static void rpmsg_release_device(struct device *dev)
+{
+	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
+
+	kfree(rpdev);
+}
+
+int rpmsg_register_device(struct rpmsg_device *rpdev)
+{
+	struct device *dev = &rpdev->dev;
+	int ret;
+
+	dev_set_name(&rpdev->dev, "%s:%s",
+		     dev_name(dev->parent), rpdev->id.name);
+
+	rpdev->dev.bus = &rpmsg_bus;
+	rpdev->dev.release = rpmsg_release_device;
+
+	ret = device_register(&rpdev->dev);
+	if (ret) {
+		dev_err(dev, "device_register failed: %d\n", ret);
+		put_device(&rpdev->dev);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(rpmsg_register_device);
+
+/*
+ * match an rpmsg channel with a channel info struct.
+ * this is used to make sure we're not creating rpmsg devices for channels
+ * that already exist.
+ */
+static int rpmsg_channel_match(struct device *dev, void *data)
+{
+	struct rpmsg_channel_info *chinfo = data;
+	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
+
+	if (chinfo->src != RPMSG_ADDR_ANY && chinfo->src != rpdev->src)
+		return 0;
+
+	if (chinfo->dst != RPMSG_ADDR_ANY && chinfo->dst != rpdev->dst)
+		return 0;
+
+	if (strncmp(chinfo->name, rpdev->id.name, RPMSG_NAME_SIZE))
+		return 0;
+
+	/* found a match ! */
+	return 1;
+}
+
+struct device *rpmsg_find_device(struct device *parent,
+				 struct rpmsg_channel_info *chinfo)
+{
+	return device_find_child(parent, chinfo, rpmsg_channel_match);
+
+}
+EXPORT_SYMBOL(rpmsg_find_device);
+
+/*
+ * find an existing channel using its name + address properties,
+ * and destroy it
+ */
+int rpmsg_unregister_device(struct device *parent,
+			    struct rpmsg_channel_info *chinfo)
+{
+	struct device *dev;
+
+	dev = rpmsg_find_device(parent, chinfo);
+	if (!dev)
+		return -EINVAL;
+
+	device_unregister(dev);
+
+	put_device(dev);
+
+	return 0;
+}
+EXPORT_SYMBOL(rpmsg_unregister_device);
+
+/**
+ * __register_rpmsg_driver() - register an rpmsg driver with the rpmsg bus
+ * @rpdrv: pointer to a struct rpmsg_driver
+ * @owner: owning module/driver
+ *
+ * Returns 0 on success, and an appropriate error value on failure.
+ */
+int __register_rpmsg_driver(struct rpmsg_driver *rpdrv, struct module *owner)
+{
+	rpdrv->drv.bus = &rpmsg_bus;
+	rpdrv->drv.owner = owner;
+	return driver_register(&rpdrv->drv);
+}
+EXPORT_SYMBOL(__register_rpmsg_driver);
+
+/**
+ * unregister_rpmsg_driver() - unregister an rpmsg driver from the rpmsg bus
+ * @rpdrv: pointer to a struct rpmsg_driver
+ *
+ * Returns 0 on success, and an appropriate error value on failure.
+ */
+void unregister_rpmsg_driver(struct rpmsg_driver *rpdrv)
+{
+	driver_unregister(&rpdrv->drv);
+}
+EXPORT_SYMBOL(unregister_rpmsg_driver);
+
+
+static int __init rpmsg_init(void)
+{
+	int ret;
+
+	ret = bus_register(&rpmsg_bus);
+	if (ret)
+		pr_err("failed to register rpmsg bus: %d\n", ret);
+
+	return ret;
+}
+postcore_initcall(rpmsg_init);
+
+static void __exit rpmsg_fini(void)
+{
+	bus_unregister(&rpmsg_bus);
+}
+module_exit(rpmsg_fini);
+
+MODULE_DESCRIPTION("remote processor messaging bus");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/rpmsg/rpmsg_internal.h b/drivers/rpmsg/rpmsg_internal.h
new file mode 100644
index 000000000000..fa91075c7956
--- /dev/null
+++ b/drivers/rpmsg/rpmsg_internal.h
@@ -0,0 +1,45 @@
+/*
+ * Virtio-based remote processor messaging bus
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * Ohad Ben-Cohen <ohad@wizery.com>
+ * Brian Swetland <swetland@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __RPMSG_INTERNAL_H__
+#define __RPMSG_INTERNAL_H__
+
+#define to_rpmsg_device(d) container_of(d, struct rpmsg_device, dev)
+#define to_rpmsg_driver(d) container_of(d, struct rpmsg_driver, drv)
+
+/**
+ * struct rpmsg_channel_info - internal channel info representation
+ * @name: name of service
+ * @src: local address
+ * @dst: destination address
+ */
+struct rpmsg_channel_info {
+	char name[RPMSG_NAME_SIZE];
+	u32 src;
+	u32 dst;
+};
+
+int rpmsg_register_device(struct rpmsg_device *rpdev);
+int rpmsg_unregister_device(struct device *parent,
+			    struct rpmsg_channel_info *chinfo);
+
+struct device *rpmsg_find_device(struct device *parent,
+				 struct rpmsg_channel_info *chinfo);
+
+#endif
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 5cadb75a225d..779c54304774 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -35,6 +35,8 @@
 #include <linux/mutex.h>
 #include <linux/of_device.h>
 
+#include "rpmsg_internal.h"
+
 /**
  * struct virtproc_info - virtual remote processor state
  * @vdev:	the virtio device
@@ -73,21 +75,6 @@ struct virtproc_info {
 	struct rpmsg_endpoint *ns_ept;
 };
 
-/**
- * struct rpmsg_channel_info - internal channel info representation
- * @name: name of service
- * @src: local address
- * @dst: destination address
- */
-struct rpmsg_channel_info {
-	char name[RPMSG_NAME_SIZE];
-	u32 src;
-	u32 dst;
-};
-
-#define to_rpmsg_device(d) container_of(d, struct rpmsg_device, dev)
-#define to_rpmsg_driver(d) container_of(d, struct rpmsg_driver, drv)
-
 /*
  * We're allocating buffers of 512 bytes each for communications. The
  * number of buffers will be computed from the number of buffers supported
@@ -129,72 +116,6 @@ static int virtio_rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data,
 				  int len, u32 dst);
 static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src,
 					   u32 dst, void *data, int len);
-static int rpmsg_register_device(struct rpmsg_device *rpdev);
-
-/* sysfs show configuration fields */
-#define rpmsg_show_attr(field, path, format_string)			\
-static ssize_t								\
-field##_show(struct device *dev,					\
-			struct device_attribute *attr, char *buf)	\
-{									\
-	struct rpmsg_device *rpdev = to_rpmsg_device(dev);		\
-									\
-	return sprintf(buf, format_string, rpdev->path);		\
-}
-
-/* for more info, see Documentation/ABI/testing/sysfs-bus-rpmsg */
-rpmsg_show_attr(name, id.name, "%s\n");
-rpmsg_show_attr(src, src, "0x%x\n");
-rpmsg_show_attr(dst, dst, "0x%x\n");
-rpmsg_show_attr(announce, announce ? "true" : "false", "%s\n");
-
-static ssize_t modalias_show(struct device *dev,
-			     struct device_attribute *attr, char *buf)
-{
-	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
-
-	return sprintf(buf, RPMSG_DEVICE_MODALIAS_FMT "\n", rpdev->id.name);
-}
-
-static struct device_attribute rpmsg_dev_attrs[] = {
-	__ATTR_RO(name),
-	__ATTR_RO(modalias),
-	__ATTR_RO(dst),
-	__ATTR_RO(src),
-	__ATTR_RO(announce),
-	__ATTR_NULL
-};
-
-/* rpmsg devices and drivers are matched using the service name */
-static inline int rpmsg_id_match(const struct rpmsg_device *rpdev,
-				 const struct rpmsg_device_id *id)
-{
-	return strncmp(id->name, rpdev->id.name, RPMSG_NAME_SIZE) == 0;
-}
-
-/* match rpmsg channel and rpmsg driver */
-static int rpmsg_dev_match(struct device *dev, struct device_driver *drv)
-{
-	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
-	struct rpmsg_driver *rpdrv = to_rpmsg_driver(drv);
-	const struct rpmsg_device_id *ids = rpdrv->id_table;
-	unsigned int i;
-
-	if (ids)
-		for (i = 0; ids[i].name[0]; i++)
-			if (rpmsg_id_match(rpdev, &ids[i]))
-				return 1;
-
-	return of_driver_match_device(dev, drv);
-}
-
-static int rpmsg_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
-	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
-
-	return add_uevent_var(env, "MODALIAS=" RPMSG_DEVICE_MODALIAS_FMT,
-					rpdev->id.name);
-}
 
 /**
  * __ept_release() - deallocate an rpmsg endpoint
@@ -266,53 +187,6 @@ free_ept:
 	return NULL;
 }
 
-/**
- * rpmsg_create_ept() - create a new rpmsg_endpoint
- * @rpdev: rpmsg channel device
- * @cb: rx callback handler
- * @priv: private data for the driver's use
- * @addr: local rpmsg address to bind with @cb
- *
- * Every rpmsg address in the system is bound to an rx callback (so when
- * inbound messages arrive, they are dispatched by the rpmsg bus using the
- * appropriate callback handler) by means of an rpmsg_endpoint struct.
- *
- * This function allows drivers to create such an endpoint, and by that,
- * bind a callback, and possibly some private data too, to an rpmsg address
- * (either one that is known in advance, or one that will be dynamically
- * assigned for them).
- *
- * Simple rpmsg drivers need not call rpmsg_create_ept, because an endpoint
- * is already created for them when they are probed by the rpmsg bus
- * (using the rx callback provided when they registered to the rpmsg bus).
- *
- * So things should just work for simple drivers: they already have an
- * endpoint, their rx callback is bound to their rpmsg address, and when
- * relevant inbound messages arrive (i.e. messages which their dst address
- * equals to the src address of their rpmsg channel), the driver's handler
- * is invoked to process it.
- *
- * That said, more complicated drivers might do need to allocate
- * additional rpmsg addresses, and bind them to different rx callbacks.
- * To accomplish that, those drivers need to call this function.
- *
- * Drivers should provide their @rpdev channel (so the new endpoint would belong
- * to the same remote processor their channel belongs to), an rx callback
- * function, an optional private data (which is provided back when the
- * rx callback is invoked), and an address they want to bind with the
- * callback. If @addr is RPMSG_ADDR_ANY, then rpmsg_create_ept will
- * dynamically assign them an available rpmsg address (drivers should have
- * a very good reason why not to always use RPMSG_ADDR_ANY here).
- *
- * Returns a pointer to the endpoint on success, or NULL on error.
- */
-struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev,
-					rpmsg_rx_cb_t cb, void *priv, u32 addr)
-{
-	return rpdev->create_ept(rpdev, cb, priv, addr);
-}
-EXPORT_SYMBOL(rpmsg_create_ept);
-
 static struct rpmsg_endpoint *virtio_rpmsg_create_ept(struct rpmsg_device *rpdev,
 						      rpmsg_rx_cb_t cb,
 						      void *priv, u32 addr)
@@ -346,62 +220,11 @@ __rpmsg_destroy_ept(struct virtproc_info *vrp, struct rpmsg_endpoint *ept)
 	kref_put(&ept->refcount, __ept_release);
 }
 
-/**
- * rpmsg_destroy_ept() - destroy an existing rpmsg endpoint
- * @ept: endpoing to destroy
- *
- * Should be used by drivers to destroy an rpmsg endpoint previously
- * created with rpmsg_create_ept().
- */
-void rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
-{
-	ept->rpdev->destroy_ept(ept);
-}
-EXPORT_SYMBOL(rpmsg_destroy_ept);
-
 static void virtio_rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
 {
 	__rpmsg_destroy_ept(ept->rpdev->vrp, ept);
 }
 
-/*
- * when an rpmsg driver is probed with a channel, we seamlessly create
- * it an endpoint, binding its rx callback to a unique local rpmsg
- * address.
- *
- * if we need to, we also announce about this channel to the remote
- * processor (needed in case the driver is exposing an rpmsg service).
- */
-static int rpmsg_dev_probe(struct device *dev)
-{
-	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
-	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
-	struct rpmsg_endpoint *ept;
-	int err;
-
-	ept = rpmsg_create_ept(rpdev, rpdrv->callback, NULL, rpdev->src);
-	if (!ept) {
-		dev_err(dev, "failed to create endpoint\n");
-		err = -ENOMEM;
-		goto out;
-	}
-
-	rpdev->ept = ept;
-	rpdev->src = ept->addr;
-
-	err = rpdrv->probe(rpdev);
-	if (err) {
-		dev_err(dev, "%s: failed: %d\n", __func__, err);
-		rpmsg_destroy_ept(ept);
-		goto out;
-	}
-
-	if (rpdev->announce_create)
-		err = rpdev->announce_create(rpdev);
-out:
-	return err;
-}
-
 static int virtio_rpmsg_announce_create(struct rpmsg_device *rpdev)
 {
 	struct virtproc_info *vrp = rpdev->vrp;
@@ -448,88 +271,6 @@ static int virtio_rpmsg_announce_destroy(struct rpmsg_device *rpdev)
 	return err;
 }
 
-static int rpmsg_dev_remove(struct device *dev)
-{
-	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
-	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
-	int err = 0;
-
-	if (rpdev->announce_destroy)
-		err = rpdev->announce_destroy(rpdev);
-
-	rpdrv->remove(rpdev);
-
-	rpmsg_destroy_ept(rpdev->ept);
-
-	return err;
-}
-
-static struct bus_type rpmsg_bus = {
-	.name		= "rpmsg",
-	.match		= rpmsg_dev_match,
-	.dev_attrs	= rpmsg_dev_attrs,
-	.uevent		= rpmsg_uevent,
-	.probe		= rpmsg_dev_probe,
-	.remove		= rpmsg_dev_remove,
-};
-
-/**
- * __register_rpmsg_driver() - register an rpmsg driver with the rpmsg bus
- * @rpdrv: pointer to a struct rpmsg_driver
- * @owner: owning module/driver
- *
- * Returns 0 on success, and an appropriate error value on failure.
- */
-int __register_rpmsg_driver(struct rpmsg_driver *rpdrv, struct module *owner)
-{
-	rpdrv->drv.bus = &rpmsg_bus;
-	rpdrv->drv.owner = owner;
-	return driver_register(&rpdrv->drv);
-}
-EXPORT_SYMBOL(__register_rpmsg_driver);
-
-/**
- * unregister_rpmsg_driver() - unregister an rpmsg driver from the rpmsg bus
- * @rpdrv: pointer to a struct rpmsg_driver
- *
- * Returns 0 on success, and an appropriate error value on failure.
- */
-void unregister_rpmsg_driver(struct rpmsg_driver *rpdrv)
-{
-	driver_unregister(&rpdrv->drv);
-}
-EXPORT_SYMBOL(unregister_rpmsg_driver);
-
-static void rpmsg_release_device(struct device *dev)
-{
-	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
-
-	kfree(rpdev);
-}
-
-/*
- * match an rpmsg channel with a channel info struct.
- * this is used to make sure we're not creating rpmsg devices for channels
- * that already exist.
- */
-static int rpmsg_device_match(struct device *dev, void *data)
-{
-	struct rpmsg_channel_info *chinfo = data;
-	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
-
-	if (chinfo->src != RPMSG_ADDR_ANY && chinfo->src != rpdev->src)
-		return 0;
-
-	if (chinfo->dst != RPMSG_ADDR_ANY && chinfo->dst != rpdev->dst)
-		return 0;
-
-	if (strncmp(chinfo->name, rpdev->id.name, RPMSG_NAME_SIZE))
-		return 0;
-
-	/* found a match ! */
-	return 1;
-}
-
 static const struct rpmsg_device virtio_rpmsg_ops = {
 	.create_ept = virtio_rpmsg_create_ept,
 	.destroy_ept = virtio_rpmsg_destroy_ept,
@@ -556,7 +297,7 @@ static struct rpmsg_device *rpmsg_create_channel(struct virtproc_info *vrp,
 	int ret;
 
 	/* make sure a similar channel doesn't already exist */
-	tmp = device_find_child(dev, chinfo, rpmsg_device_match);
+	tmp = rpmsg_find_device(dev, chinfo);
 	if (tmp) {
 		/* decrement the matched device's refcount back */
 		put_device(tmp);
@@ -592,47 +333,6 @@ static struct rpmsg_device *rpmsg_create_channel(struct virtproc_info *vrp,
 	return rpdev;
 }
 
-static int rpmsg_register_device(struct rpmsg_device *rpdev)
-{
-	struct device *dev = &rpdev->dev;
-	int ret;
-
-	dev_set_name(&rpdev->dev, "%s:%s",
-		     dev_name(dev->parent), rpdev->id.name);
-
-	rpdev->dev.bus = &rpmsg_bus;
-	rpdev->dev.release = rpmsg_release_device;
-
-	ret = device_register(&rpdev->dev);
-	if (ret) {
-		dev_err(dev, "device_register failed: %d\n", ret);
-		put_device(&rpdev->dev);
-	}
-
-	return ret;
-}
-
-/*
- * find an existing channel using its name + address properties,
- * and destroy it
- */
-static int rpmsg_destroy_channel(struct virtproc_info *vrp,
-				 struct rpmsg_channel_info *chinfo)
-{
-	struct virtio_device *vdev = vrp->vdev;
-	struct device *dev;
-
-	dev = device_find_child(&vdev->dev, chinfo, rpmsg_device_match);
-	if (!dev)
-		return -EINVAL;
-
-	device_unregister(dev);
-
-	put_device(dev);
-
-	return 0;
-}
-
 /* super simple buffer "allocator" that is just enough for now */
 static void *get_a_tx_buf(struct virtproc_info *vrp)
 {
@@ -844,31 +544,6 @@ out:
 	return err;
 }
 
-/**
- * rpmsg_send() - send a message across to the remote processor
- * @ept: the rpmsg endpoint
- * @data: payload of message
- * @len: length of payload
- *
- * This function sends @data of length @len on the @ept endpoint.
- * The message will be sent to the remote processor which the @ept
- * endpoint belongs to, using @ept's address and its associated rpmsg
- * device destination addresses.
- * In case there are no TX buffers available, the function will block until
- * one becomes available, or a timeout of 15 seconds elapses. When the latter
- * happens, -ERESTARTSYS is returned.
- *
- * Can only be called from process context (for now).
- *
- * Returns 0 on success and an appropriate error value on failure.
- */
-int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
-{
-	struct rpmsg_device *rpdev = ept->rpdev;
-
-	return rpdev->send(ept, data, len);
-}
-
 static int virtio_rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
 {
 	struct rpmsg_device *rpdev = ept->rpdev;
@@ -877,32 +552,6 @@ static int virtio_rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
 }
 
-/**
- * rpmsg_sendto() - send a message across to the remote processor, specify dst
- * @ept: the rpmsg endpoint
- * @data: payload of message
- * @len: length of payload
- * @dst: destination address
- *
- * This function sends @data of length @len to the remote @dst address.
- * The message will be sent to the remote processor which the @ept
- * endpoint belongs to, using @ept's address as source.
- * In case there are no TX buffers available, the function will block until
- * one becomes available, or a timeout of 15 seconds elapses. When the latter
- * happens, -ERESTARTSYS is returned.
- *
- * Can only be called from process context (for now).
- *
- * Returns 0 on success and an appropriate error value on failure.
- */
-int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
-{
-	struct rpmsg_device *rpdev = ept->rpdev;
-
-	return rpdev->sendto(ept, data, len, dst);
-}
-EXPORT_SYMBOL(rpmsg_sendto);
-
 static int virtio_rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len,
 			       u32 dst)
 {
@@ -912,35 +561,6 @@ static int virtio_rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len,
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
 }
 
-/**
- * rpmsg_send_offchannel() - send a message using explicit src/dst addresses
- * @ept: the rpmsg endpoint
- * @src: source address
- * @dst: destination address
- * @data: payload of message
- * @len: length of payload
- *
- * This function sends @data of length @len to the remote @dst address,
- * and uses @src as the source address.
- * The message will be sent to the remote processor which the @ept
- * endpoint belongs to.
- * In case there are no TX buffers available, the function will block until
- * one becomes available, or a timeout of 15 seconds elapses. When the latter
- * happens, -ERESTARTSYS is returned.
- *
- * Can only be called from process context (for now).
- *
- * Returns 0 on success and an appropriate error value on failure.
- */
-int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
-			  void *data, int len)
-{
-	struct rpmsg_device *rpdev = ept->rpdev;
-
-	return rpdev->send_offchannel(ept, src, dst, data, len);
-}
-EXPORT_SYMBOL(rpmsg_send_offchannel);
-
 static int virtio_rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src,
 					u32 dst, void *data, int len)
 {
@@ -949,31 +569,6 @@ static int virtio_rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src,
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
 }
 
-/**
- * rpmsg_send() - send a message across to the remote processor
- * @ept: the rpmsg endpoint
- * @data: payload of message
- * @len: length of payload
- *
- * This function sends @data of length @len on the @ept endpoint.
- * The message will be sent to the remote processor which the @ept
- * endpoint belongs to, using @ept's addres as source and its associated
- * rpdev's address as destination.
- * In case there are no TX buffers available, the function will immediately
- * return -ENOMEM without waiting until one becomes available.
- *
- * Can only be called from process context (for now).
- *
- * Returns 0 on success and an appropriate error value on failure.
- */
-int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
-{
-	struct rpmsg_device *rpdev = ept->rpdev;
-
-	return rpdev->trysend(ept, data, len);
-}
-EXPORT_SYMBOL(rpmsg_trysend);
-
 static int virtio_rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
 {
 	struct rpmsg_device *rpdev = ept->rpdev;
@@ -982,31 +577,6 @@ static int virtio_rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
 }
 
-/**
- * rpmsg_sendto() - send a message across to the remote processor, specify dst
- * @ept: the rpmsg endpoint
- * @data: payload of message
- * @len: length of payload
- * @dst: destination address
- *
- * This function sends @data of length @len to the remote @dst address.
- * The message will be sent to the remote processor which the @ept
- * endpoint belongs to, using @ept's address as source.
- * In case there are no TX buffers available, the function will immediately
- * return -ENOMEM without waiting until one becomes available.
- *
- * Can only be called from process context (for now).
- *
- * Returns 0 on success and an appropriate error value on failure.
- */
-int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
-{
-	struct rpmsg_device *rpdev = ept->rpdev;
-
-	return rpdev->trysendto(ept, data, len, dst);
-}
-EXPORT_SYMBOL(rpmsg_trysendto);
-
 static int virtio_rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data,
 				  int len, u32 dst)
 {
@@ -1016,34 +586,6 @@ static int virtio_rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data,
 	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
 }
 
-/**
- * rpmsg_send_offchannel() - send a message using explicit src/dst addresses
- * @ept: the rpmsg endpoint
- * @src: source address
- * @dst: destination address
- * @data: payload of message
- * @len: length of payload
- *
- * This function sends @data of length @len to the remote @dst address,
- * and uses @src as the source address.
- * The message will be sent to the remote processor which the @ept
- * endpoint belongs to.
- * In case there are no TX buffers available, the function will immediately
- * return -ENOMEM without waiting until one becomes available.
- *
- * Can only be called from process context (for now).
- *
- * Returns 0 on success and an appropriate error value on failure.
- */
-int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
-			     void *data, int len)
-{
-	struct rpmsg_device *rpdev = ept->rpdev;
-
-	return rpdev->trysend_offchannel(ept, src, dst, data, len);
-}
-EXPORT_SYMBOL(rpmsg_trysend_offchannel);
-
 static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src,
 					   u32 dst, void *data, int len)
 {
@@ -1208,7 +750,7 @@ static void rpmsg_ns_cb(struct rpmsg_device *rpdev, void *data, int len,
 	chinfo.dst = msg->addr;
 
 	if (msg->flags & RPMSG_NS_DESTROY) {
-		ret = rpmsg_destroy_channel(vrp, &chinfo);
+		ret = rpmsg_unregister_device(&vrp->vdev->dev, &chinfo);
 		if (ret)
 			dev_err(dev, "rpmsg_destroy_channel failed: %d\n", ret);
 	} else {
@@ -1393,17 +935,9 @@ static int __init rpmsg_init(void)
 {
 	int ret;
 
-	ret = bus_register(&rpmsg_bus);
-	if (ret) {
-		pr_err("failed to register rpmsg bus: %d\n", ret);
-		return ret;
-	}
-
 	ret = register_virtio_driver(&virtio_ipc_driver);
-	if (ret) {
+	if (ret)
 		pr_err("failed to register virtio driver: %d\n", ret);
-		bus_unregister(&rpmsg_bus);
-	}
 
 	return ret;
 }
@@ -1412,7 +946,6 @@ subsys_initcall(rpmsg_init);
 static void __exit rpmsg_fini(void)
 {
 	unregister_virtio_driver(&virtio_ipc_driver);
-	bus_unregister(&rpmsg_bus);
 }
 module_exit(rpmsg_fini);
 
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 09/14] rpmsg: Internalize rpmsg core ops
  2016-08-16  0:17 ` Bjorn Andersson
@ 2016-08-16  0:17   ` Bjorn Andersson
  -1 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-16  0:17 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson
  Cc: linux-remoteproc, linux-arm-msm, linux-arm-kernel, linux-kernel

Introduce a container struct rpmsg_channel around the rpmsg_device to
keep rpmsg internal data hidden from the public API.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/rpmsg/rpmsg_core.c       | 42 +++++++++++++++++++++++-----------------
 drivers/rpmsg/rpmsg_internal.h   | 30 ++++++++++++++++++++++++++++
 drivers/rpmsg/virtio_rpmsg_bus.c | 10 ++++++----
 include/linux/rpmsg.h            | 17 ----------------
 4 files changed, 60 insertions(+), 39 deletions(-)

diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
index 73bbc5ea5778..6f7cc79f7229 100644
--- a/drivers/rpmsg/rpmsg_core.c
+++ b/drivers/rpmsg/rpmsg_core.c
@@ -80,7 +80,9 @@
 struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev,
 				rpmsg_rx_cb_t cb, void *priv, u32 addr)
 {
-	return rpdev->create_ept(rpdev, cb, priv, addr);
+	struct rpmsg_channel *rpch = to_rpmsg_channel(&rpdev->dev);
+
+	return rpch->create_ept(rpdev, cb, priv, addr);
 }
 EXPORT_SYMBOL(rpmsg_create_ept);
 
@@ -93,7 +95,9 @@ EXPORT_SYMBOL(rpmsg_create_ept);
  */
 void rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
 {
-	ept->rpdev->destroy_ept(ept);
+	struct rpmsg_channel *rpch = to_rpmsg_channel(&ept->rpdev->dev);
+
+	rpch->destroy_ept(ept);
 }
 EXPORT_SYMBOL(rpmsg_destroy_ept);
 
@@ -117,9 +121,9 @@ EXPORT_SYMBOL(rpmsg_destroy_ept);
  */
 int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
 {
-	struct rpmsg_device *rpdev = ept->rpdev;
+	struct rpmsg_channel *rpch = to_rpmsg_channel(&ept->rpdev->dev);
 
-	return rpdev->send(ept, data, len);
+	return rpch->send(ept, data, len);
 }
 
 /**
@@ -142,9 +146,9 @@ int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
  */
 int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
 {
-	struct rpmsg_device *rpdev = ept->rpdev;
+	struct rpmsg_channel *rpch = to_rpmsg_channel(&ept->rpdev->dev);
 
-	return rpdev->sendto(ept, data, len, dst);
+	return rpch->sendto(ept, data, len, dst);
 }
 EXPORT_SYMBOL(rpmsg_sendto);
 
@@ -171,9 +175,9 @@ EXPORT_SYMBOL(rpmsg_sendto);
 int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
 			  void *data, int len)
 {
-	struct rpmsg_device *rpdev = ept->rpdev;
+	struct rpmsg_channel *rpch = to_rpmsg_channel(&ept->rpdev->dev);
 
-	return rpdev->send_offchannel(ept, src, dst, data, len);
+	return rpch->send_offchannel(ept, src, dst, data, len);
 }
 EXPORT_SYMBOL(rpmsg_send_offchannel);
 
@@ -196,9 +200,9 @@ EXPORT_SYMBOL(rpmsg_send_offchannel);
  */
 int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
 {
-	struct rpmsg_device *rpdev = ept->rpdev;
+	struct rpmsg_channel *rpch = to_rpmsg_channel(&ept->rpdev->dev);
 
-	return rpdev->trysend(ept, data, len);
+	return rpch->trysend(ept, data, len);
 }
 EXPORT_SYMBOL(rpmsg_trysend);
 
@@ -221,9 +225,9 @@ EXPORT_SYMBOL(rpmsg_trysend);
  */
 int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
 {
-	struct rpmsg_device *rpdev = ept->rpdev;
+	struct rpmsg_channel *rpch = to_rpmsg_channel(&ept->rpdev->dev);
 
-	return rpdev->trysendto(ept, data, len, dst);
+	return rpch->trysendto(ept, data, len, dst);
 }
 EXPORT_SYMBOL(rpmsg_trysendto);
 
@@ -249,9 +253,9 @@ EXPORT_SYMBOL(rpmsg_trysendto);
 int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
 			     void *data, int len)
 {
-	struct rpmsg_device *rpdev = ept->rpdev;
+	struct rpmsg_channel *rpch = to_rpmsg_channel(&ept->rpdev->dev);
 
-	return rpdev->trysend_offchannel(ept, src, dst, data, len);
+	return rpch->trysend_offchannel(ept, src, dst, data, len);
 }
 EXPORT_SYMBOL(rpmsg_trysend_offchannel);
 
@@ -330,6 +334,7 @@ static int rpmsg_uevent(struct device *dev, struct kobj_uevent_env *env)
  */
 static int rpmsg_dev_probe(struct device *dev)
 {
+	struct rpmsg_channel *rpch = to_rpmsg_channel(dev);
 	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
 	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
 	struct rpmsg_endpoint *ept;
@@ -352,20 +357,21 @@ static int rpmsg_dev_probe(struct device *dev)
 		goto out;
 	}
 
-	if (rpdev->announce_create)
-		err = rpdev->announce_create(rpdev);
+	if (rpch->announce_create)
+		err = rpch->announce_create(rpdev);
 out:
 	return err;
 }
 
 static int rpmsg_dev_remove(struct device *dev)
 {
+	struct rpmsg_channel *rpch = to_rpmsg_channel(dev);
 	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
 	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
 	int err = 0;
 
-	if (rpdev->announce_destroy)
-		err = rpdev->announce_destroy(rpdev);
+	if (rpch->announce_destroy)
+		err = rpch->announce_destroy(rpdev);
 
 	rpdrv->remove(rpdev);
 
diff --git a/drivers/rpmsg/rpmsg_internal.h b/drivers/rpmsg/rpmsg_internal.h
index fa91075c7956..54083bf54d14 100644
--- a/drivers/rpmsg/rpmsg_internal.h
+++ b/drivers/rpmsg/rpmsg_internal.h
@@ -35,6 +35,36 @@ struct rpmsg_channel_info {
 	u32 dst;
 };
 
+struct rpmsg_channel {
+	struct rpmsg_device rpdev;
+
+	struct rpmsg_endpoint *(*create_ept)(struct rpmsg_device *rpdev,
+					     rpmsg_rx_cb_t cb, void *priv,
+					     u32 addr);
+	void (*destroy_ept)(struct rpmsg_endpoint *ept);
+
+	int (*send)(struct rpmsg_endpoint *ept, void *data, int len);
+	int (*sendto)(struct rpmsg_endpoint *ept, void *data, int len, u32 dst);
+	int (*send_offchannel)(struct rpmsg_endpoint *ept, u32 src, u32 dst,
+				  void *data, int len);
+
+	int (*trysend)(struct rpmsg_endpoint *ept, void *data, int len);
+	int (*trysendto)(struct rpmsg_endpoint *ept, void *data, int len,
+			 u32 dst);
+	int (*trysend_offchannel)(struct rpmsg_endpoint *ept, u32 src, u32 dst,
+				  void *data, int len);
+
+	int (*announce_create)(struct rpmsg_device *rpdev);
+	int (*announce_destroy)(struct rpmsg_device *rpdev);
+};
+
+static inline struct rpmsg_channel *to_rpmsg_channel(struct device *d)
+{
+	struct rpmsg_device *rpdev = to_rpmsg_device(d);
+
+	return container_of(rpdev, struct rpmsg_channel, rpdev);
+}
+
 int rpmsg_register_device(struct rpmsg_device *rpdev);
 int rpmsg_unregister_device(struct device *parent,
 			    struct rpmsg_channel_info *chinfo);
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 779c54304774..d08facbcd30a 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -271,7 +271,7 @@ static int virtio_rpmsg_announce_destroy(struct rpmsg_device *rpdev)
 	return err;
 }
 
-static const struct rpmsg_device virtio_rpmsg_ops = {
+static const struct rpmsg_channel virtio_rpmsg_ops = {
 	.create_ept = virtio_rpmsg_create_ept,
 	.destroy_ept = virtio_rpmsg_destroy_ept,
 	.send = virtio_rpmsg_send,
@@ -292,6 +292,7 @@ static const struct rpmsg_device virtio_rpmsg_ops = {
 static struct rpmsg_device *rpmsg_create_channel(struct virtproc_info *vrp,
 						 struct rpmsg_channel_info *chinfo)
 {
+	struct rpmsg_channel *rpch;
 	struct rpmsg_device *rpdev;
 	struct device *tmp, *dev = &vrp->vdev->dev;
 	int ret;
@@ -306,13 +307,14 @@ static struct rpmsg_device *rpmsg_create_channel(struct virtproc_info *vrp,
 		return NULL;
 	}
 
-	rpdev = kzalloc(sizeof(*rpdev), GFP_KERNEL);
-	if (!rpdev)
+	rpch = kzalloc(sizeof(*rpch), GFP_KERNEL);
+	if (!rpch)
 		return NULL;
 
 	/* Assign callbacks for rpmsg_channel */
-	*rpdev = virtio_rpmsg_ops;
+	*rpch = virtio_rpmsg_ops;
 
+	rpdev = &rpch->rpdev;
 	rpdev->vrp = vrp;
 	rpdev->src = chinfo->src;
 	rpdev->dst = chinfo->dst;
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index 0b290ae18e70..3d0ff950c0d6 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -119,23 +119,6 @@ struct rpmsg_device {
 	u32 dst;
 	struct rpmsg_endpoint *ept;
 	bool announce;
-
-	struct rpmsg_endpoint *(*create_ept)(struct rpmsg_device *rpdev,
-					    rpmsg_rx_cb_t cb, void *priv, u32 addr);
-	void (*destroy_ept)(struct rpmsg_endpoint *ept);
-
-	int (*send)(struct rpmsg_endpoint *ept, void *data, int len);
-	int (*sendto)(struct rpmsg_endpoint *ept, void *data, int len, u32 dst);
-	int (*send_offchannel)(struct rpmsg_endpoint *ept, u32 src, u32 dst,
-				  void *data, int len);
-
-	int (*trysend)(struct rpmsg_endpoint *ept, void *data, int len);
-	int (*trysendto)(struct rpmsg_endpoint *ept, void *data, int len, u32 dst);
-	int (*trysend_offchannel)(struct rpmsg_endpoint *ept, u32 src, u32 dst,
-			     void *data, int len);
-
-	int (*announce_create)(struct rpmsg_device *ept);
-	int (*announce_destroy)(struct rpmsg_device *ept);
 };
 
 /**
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 09/14] rpmsg: Internalize rpmsg core ops
@ 2016-08-16  0:17   ` Bjorn Andersson
  0 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-16  0:17 UTC (permalink / raw)
  To: linux-arm-kernel

Introduce a container struct rpmsg_channel around the rpmsg_device to
keep rpmsg internal data hidden from the public API.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/rpmsg/rpmsg_core.c       | 42 +++++++++++++++++++++++-----------------
 drivers/rpmsg/rpmsg_internal.h   | 30 ++++++++++++++++++++++++++++
 drivers/rpmsg/virtio_rpmsg_bus.c | 10 ++++++----
 include/linux/rpmsg.h            | 17 ----------------
 4 files changed, 60 insertions(+), 39 deletions(-)

diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
index 73bbc5ea5778..6f7cc79f7229 100644
--- a/drivers/rpmsg/rpmsg_core.c
+++ b/drivers/rpmsg/rpmsg_core.c
@@ -80,7 +80,9 @@
 struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev,
 				rpmsg_rx_cb_t cb, void *priv, u32 addr)
 {
-	return rpdev->create_ept(rpdev, cb, priv, addr);
+	struct rpmsg_channel *rpch = to_rpmsg_channel(&rpdev->dev);
+
+	return rpch->create_ept(rpdev, cb, priv, addr);
 }
 EXPORT_SYMBOL(rpmsg_create_ept);
 
@@ -93,7 +95,9 @@ EXPORT_SYMBOL(rpmsg_create_ept);
  */
 void rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
 {
-	ept->rpdev->destroy_ept(ept);
+	struct rpmsg_channel *rpch = to_rpmsg_channel(&ept->rpdev->dev);
+
+	rpch->destroy_ept(ept);
 }
 EXPORT_SYMBOL(rpmsg_destroy_ept);
 
@@ -117,9 +121,9 @@ EXPORT_SYMBOL(rpmsg_destroy_ept);
  */
 int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
 {
-	struct rpmsg_device *rpdev = ept->rpdev;
+	struct rpmsg_channel *rpch = to_rpmsg_channel(&ept->rpdev->dev);
 
-	return rpdev->send(ept, data, len);
+	return rpch->send(ept, data, len);
 }
 
 /**
@@ -142,9 +146,9 @@ int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
  */
 int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
 {
-	struct rpmsg_device *rpdev = ept->rpdev;
+	struct rpmsg_channel *rpch = to_rpmsg_channel(&ept->rpdev->dev);
 
-	return rpdev->sendto(ept, data, len, dst);
+	return rpch->sendto(ept, data, len, dst);
 }
 EXPORT_SYMBOL(rpmsg_sendto);
 
@@ -171,9 +175,9 @@ EXPORT_SYMBOL(rpmsg_sendto);
 int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
 			  void *data, int len)
 {
-	struct rpmsg_device *rpdev = ept->rpdev;
+	struct rpmsg_channel *rpch = to_rpmsg_channel(&ept->rpdev->dev);
 
-	return rpdev->send_offchannel(ept, src, dst, data, len);
+	return rpch->send_offchannel(ept, src, dst, data, len);
 }
 EXPORT_SYMBOL(rpmsg_send_offchannel);
 
@@ -196,9 +200,9 @@ EXPORT_SYMBOL(rpmsg_send_offchannel);
  */
 int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
 {
-	struct rpmsg_device *rpdev = ept->rpdev;
+	struct rpmsg_channel *rpch = to_rpmsg_channel(&ept->rpdev->dev);
 
-	return rpdev->trysend(ept, data, len);
+	return rpch->trysend(ept, data, len);
 }
 EXPORT_SYMBOL(rpmsg_trysend);
 
@@ -221,9 +225,9 @@ EXPORT_SYMBOL(rpmsg_trysend);
  */
 int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
 {
-	struct rpmsg_device *rpdev = ept->rpdev;
+	struct rpmsg_channel *rpch = to_rpmsg_channel(&ept->rpdev->dev);
 
-	return rpdev->trysendto(ept, data, len, dst);
+	return rpch->trysendto(ept, data, len, dst);
 }
 EXPORT_SYMBOL(rpmsg_trysendto);
 
@@ -249,9 +253,9 @@ EXPORT_SYMBOL(rpmsg_trysendto);
 int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
 			     void *data, int len)
 {
-	struct rpmsg_device *rpdev = ept->rpdev;
+	struct rpmsg_channel *rpch = to_rpmsg_channel(&ept->rpdev->dev);
 
-	return rpdev->trysend_offchannel(ept, src, dst, data, len);
+	return rpch->trysend_offchannel(ept, src, dst, data, len);
 }
 EXPORT_SYMBOL(rpmsg_trysend_offchannel);
 
@@ -330,6 +334,7 @@ static int rpmsg_uevent(struct device *dev, struct kobj_uevent_env *env)
  */
 static int rpmsg_dev_probe(struct device *dev)
 {
+	struct rpmsg_channel *rpch = to_rpmsg_channel(dev);
 	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
 	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
 	struct rpmsg_endpoint *ept;
@@ -352,20 +357,21 @@ static int rpmsg_dev_probe(struct device *dev)
 		goto out;
 	}
 
-	if (rpdev->announce_create)
-		err = rpdev->announce_create(rpdev);
+	if (rpch->announce_create)
+		err = rpch->announce_create(rpdev);
 out:
 	return err;
 }
 
 static int rpmsg_dev_remove(struct device *dev)
 {
+	struct rpmsg_channel *rpch = to_rpmsg_channel(dev);
 	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
 	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
 	int err = 0;
 
-	if (rpdev->announce_destroy)
-		err = rpdev->announce_destroy(rpdev);
+	if (rpch->announce_destroy)
+		err = rpch->announce_destroy(rpdev);
 
 	rpdrv->remove(rpdev);
 
diff --git a/drivers/rpmsg/rpmsg_internal.h b/drivers/rpmsg/rpmsg_internal.h
index fa91075c7956..54083bf54d14 100644
--- a/drivers/rpmsg/rpmsg_internal.h
+++ b/drivers/rpmsg/rpmsg_internal.h
@@ -35,6 +35,36 @@ struct rpmsg_channel_info {
 	u32 dst;
 };
 
+struct rpmsg_channel {
+	struct rpmsg_device rpdev;
+
+	struct rpmsg_endpoint *(*create_ept)(struct rpmsg_device *rpdev,
+					     rpmsg_rx_cb_t cb, void *priv,
+					     u32 addr);
+	void (*destroy_ept)(struct rpmsg_endpoint *ept);
+
+	int (*send)(struct rpmsg_endpoint *ept, void *data, int len);
+	int (*sendto)(struct rpmsg_endpoint *ept, void *data, int len, u32 dst);
+	int (*send_offchannel)(struct rpmsg_endpoint *ept, u32 src, u32 dst,
+				  void *data, int len);
+
+	int (*trysend)(struct rpmsg_endpoint *ept, void *data, int len);
+	int (*trysendto)(struct rpmsg_endpoint *ept, void *data, int len,
+			 u32 dst);
+	int (*trysend_offchannel)(struct rpmsg_endpoint *ept, u32 src, u32 dst,
+				  void *data, int len);
+
+	int (*announce_create)(struct rpmsg_device *rpdev);
+	int (*announce_destroy)(struct rpmsg_device *rpdev);
+};
+
+static inline struct rpmsg_channel *to_rpmsg_channel(struct device *d)
+{
+	struct rpmsg_device *rpdev = to_rpmsg_device(d);
+
+	return container_of(rpdev, struct rpmsg_channel, rpdev);
+}
+
 int rpmsg_register_device(struct rpmsg_device *rpdev);
 int rpmsg_unregister_device(struct device *parent,
 			    struct rpmsg_channel_info *chinfo);
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 779c54304774..d08facbcd30a 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -271,7 +271,7 @@ static int virtio_rpmsg_announce_destroy(struct rpmsg_device *rpdev)
 	return err;
 }
 
-static const struct rpmsg_device virtio_rpmsg_ops = {
+static const struct rpmsg_channel virtio_rpmsg_ops = {
 	.create_ept = virtio_rpmsg_create_ept,
 	.destroy_ept = virtio_rpmsg_destroy_ept,
 	.send = virtio_rpmsg_send,
@@ -292,6 +292,7 @@ static const struct rpmsg_device virtio_rpmsg_ops = {
 static struct rpmsg_device *rpmsg_create_channel(struct virtproc_info *vrp,
 						 struct rpmsg_channel_info *chinfo)
 {
+	struct rpmsg_channel *rpch;
 	struct rpmsg_device *rpdev;
 	struct device *tmp, *dev = &vrp->vdev->dev;
 	int ret;
@@ -306,13 +307,14 @@ static struct rpmsg_device *rpmsg_create_channel(struct virtproc_info *vrp,
 		return NULL;
 	}
 
-	rpdev = kzalloc(sizeof(*rpdev), GFP_KERNEL);
-	if (!rpdev)
+	rpch = kzalloc(sizeof(*rpch), GFP_KERNEL);
+	if (!rpch)
 		return NULL;
 
 	/* Assign callbacks for rpmsg_channel */
-	*rpdev = virtio_rpmsg_ops;
+	*rpch = virtio_rpmsg_ops;
 
+	rpdev = &rpch->rpdev;
 	rpdev->vrp = vrp;
 	rpdev->src = chinfo->src;
 	rpdev->dst = chinfo->dst;
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index 0b290ae18e70..3d0ff950c0d6 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -119,23 +119,6 @@ struct rpmsg_device {
 	u32 dst;
 	struct rpmsg_endpoint *ept;
 	bool announce;
-
-	struct rpmsg_endpoint *(*create_ept)(struct rpmsg_device *rpdev,
-					    rpmsg_rx_cb_t cb, void *priv, u32 addr);
-	void (*destroy_ept)(struct rpmsg_endpoint *ept);
-
-	int (*send)(struct rpmsg_endpoint *ept, void *data, int len);
-	int (*sendto)(struct rpmsg_endpoint *ept, void *data, int len, u32 dst);
-	int (*send_offchannel)(struct rpmsg_endpoint *ept, u32 src, u32 dst,
-				  void *data, int len);
-
-	int (*trysend)(struct rpmsg_endpoint *ept, void *data, int len);
-	int (*trysendto)(struct rpmsg_endpoint *ept, void *data, int len, u32 dst);
-	int (*trysend_offchannel)(struct rpmsg_endpoint *ept, u32 src, u32 dst,
-			     void *data, int len);
-
-	int (*announce_create)(struct rpmsg_device *ept);
-	int (*announce_destroy)(struct rpmsg_device *ept);
 };
 
 /**
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 10/14] rpmsg: virtio: Internalize vrp pointer
  2016-08-16  0:17 ` Bjorn Andersson
@ 2016-08-16  0:17   ` Bjorn Andersson
  -1 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-16  0:17 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson
  Cc: linux-remoteproc, linux-arm-msm, linux-arm-kernel, linux-kernel

Create a container struct virtio_rpmsg_channel around the rpmsg_channel
to keep virtio backend information separate from the rpmsg and public
API.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/rpmsg/virtio_rpmsg_bus.c | 45 ++++++++++++++++++++++++++++++----------
 include/linux/rpmsg.h            |  3 ---
 2 files changed, 34 insertions(+), 14 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index d08facbcd30a..6ad4c657aaf4 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -75,6 +75,21 @@ struct virtproc_info {
 	struct rpmsg_endpoint *ns_ept;
 };
 
+/**
+ * @vrp: the remote processor this channel belongs to
+ */
+struct virtio_rpmsg_channel {
+	struct rpmsg_channel rpch;
+
+	struct virtproc_info *vrp;
+};
+
+static inline struct virtio_rpmsg_channel *to_virtio_rpmsg_channel(struct device *d)
+{
+	struct rpmsg_channel *rpch = to_rpmsg_channel(d);
+	return container_of(rpch, struct virtio_rpmsg_channel, rpch);
+}
+
 /*
  * We're allocating buffers of 512 bytes each for communications. The
  * number of buffers will be computed from the number of buffers supported
@@ -191,7 +206,8 @@ static struct rpmsg_endpoint *virtio_rpmsg_create_ept(struct rpmsg_device *rpdev
 						      rpmsg_rx_cb_t cb,
 						      void *priv, u32 addr)
 {
-	return __rpmsg_create_ept(rpdev->vrp, rpdev, cb, priv, addr);
+	struct virtio_rpmsg_channel *vch = to_virtio_rpmsg_channel(&rpdev->dev);
+	return __rpmsg_create_ept(vch->vrp, rpdev, cb, priv, addr);
 }
 
 /**
@@ -222,12 +238,14 @@ __rpmsg_destroy_ept(struct virtproc_info *vrp, struct rpmsg_endpoint *ept)
 
 static void virtio_rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
 {
-	__rpmsg_destroy_ept(ept->rpdev->vrp, ept);
+	struct virtio_rpmsg_channel *vch = to_virtio_rpmsg_channel(&ept->rpdev->dev);
+	__rpmsg_destroy_ept(vch->vrp, ept);
 }
 
 static int virtio_rpmsg_announce_create(struct rpmsg_device *rpdev)
 {
-	struct virtproc_info *vrp = rpdev->vrp;
+	struct virtio_rpmsg_channel *vch = to_virtio_rpmsg_channel(&rpdev->dev);
+	struct virtproc_info *vrp = vch->vrp;
 	struct device *dev = &rpdev->dev;
 	int err = 0;
 
@@ -250,7 +268,8 @@ static int virtio_rpmsg_announce_create(struct rpmsg_device *rpdev)
 
 static int virtio_rpmsg_announce_destroy(struct rpmsg_device *rpdev)
 {
-	struct virtproc_info *vrp = rpdev->vrp;
+	struct virtio_rpmsg_channel *vch = to_virtio_rpmsg_channel(&rpdev->dev);
+	struct virtproc_info *vrp = vch->vrp;
 	struct device *dev = &rpdev->dev;
 	int err = 0;
 
@@ -292,7 +311,7 @@ static const struct rpmsg_channel virtio_rpmsg_ops = {
 static struct rpmsg_device *rpmsg_create_channel(struct virtproc_info *vrp,
 						 struct rpmsg_channel_info *chinfo)
 {
-	struct rpmsg_channel *rpch;
+	struct virtio_rpmsg_channel *vch;
 	struct rpmsg_device *rpdev;
 	struct device *tmp, *dev = &vrp->vdev->dev;
 	int ret;
@@ -307,15 +326,18 @@ static struct rpmsg_device *rpmsg_create_channel(struct virtproc_info *vrp,
 		return NULL;
 	}
 
-	rpch = kzalloc(sizeof(*rpch), GFP_KERNEL);
-	if (!rpch)
+	vch = kzalloc(sizeof(*vch), GFP_KERNEL);
+	if (!vch)
 		return NULL;
 
+	/* Link the channel to our vrp */
+	vch->vrp = vrp;
+
 	/* Assign callbacks for rpmsg_channel */
-	*rpch = virtio_rpmsg_ops;
+	vch->rpch = virtio_rpmsg_ops;
 
-	rpdev = &rpch->rpdev;
-	rpdev->vrp = vrp;
+	/* Assign public information to the rpmsg_device */
+	rpdev = &vch->rpch.rpdev;
 	rpdev->src = chinfo->src;
 	rpdev->dst = chinfo->dst;
 
@@ -453,7 +475,8 @@ static int rpmsg_send_offchannel_raw(struct rpmsg_device *rpdev,
 				     u32 src, u32 dst,
 				     void *data, int len, bool wait)
 {
-	struct virtproc_info *vrp = rpdev->vrp;
+	struct virtio_rpmsg_channel *vch = to_virtio_rpmsg_channel(&rpdev->dev);
+	struct virtproc_info *vrp = vch->vrp;
 	struct device *dev = &rpdev->dev;
 	struct scatterlist sg;
 	struct rpmsg_hdr *msg;
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index 3d0ff950c0d6..a5679b9b6102 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -95,7 +95,6 @@ enum rpmsg_ns_flags {
 
 #define RPMSG_ADDR_ANY		0xFFFFFFFF
 
-struct virtproc_info;
 struct rpmsg_device;
 struct rpmsg_endpoint;
 
@@ -103,7 +102,6 @@ typedef void (*rpmsg_rx_cb_t)(struct rpmsg_device *, void *, int, void *, u32);
 
 /**
  * rpmsg_device - device that belong to the rpmsg bus
- * @vrp: the remote processor this channel belongs to
  * @dev: the device struct
  * @id: device id (used to match between rpmsg drivers and devices)
  * @src: local address
@@ -112,7 +110,6 @@ typedef void (*rpmsg_rx_cb_t)(struct rpmsg_device *, void *, int, void *, u32);
  * @announce: if set, rpmsg will announce the creation/removal of this channel
  */
 struct rpmsg_device {
-	struct virtproc_info *vrp;
 	struct device dev;
 	struct rpmsg_device_id id;
 	u32 src;
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 10/14] rpmsg: virtio: Internalize vrp pointer
@ 2016-08-16  0:17   ` Bjorn Andersson
  0 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-16  0:17 UTC (permalink / raw)
  To: linux-arm-kernel

Create a container struct virtio_rpmsg_channel around the rpmsg_channel
to keep virtio backend information separate from the rpmsg and public
API.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/rpmsg/virtio_rpmsg_bus.c | 45 ++++++++++++++++++++++++++++++----------
 include/linux/rpmsg.h            |  3 ---
 2 files changed, 34 insertions(+), 14 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index d08facbcd30a..6ad4c657aaf4 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -75,6 +75,21 @@ struct virtproc_info {
 	struct rpmsg_endpoint *ns_ept;
 };
 
+/**
+ * @vrp: the remote processor this channel belongs to
+ */
+struct virtio_rpmsg_channel {
+	struct rpmsg_channel rpch;
+
+	struct virtproc_info *vrp;
+};
+
+static inline struct virtio_rpmsg_channel *to_virtio_rpmsg_channel(struct device *d)
+{
+	struct rpmsg_channel *rpch = to_rpmsg_channel(d);
+	return container_of(rpch, struct virtio_rpmsg_channel, rpch);
+}
+
 /*
  * We're allocating buffers of 512 bytes each for communications. The
  * number of buffers will be computed from the number of buffers supported
@@ -191,7 +206,8 @@ static struct rpmsg_endpoint *virtio_rpmsg_create_ept(struct rpmsg_device *rpdev
 						      rpmsg_rx_cb_t cb,
 						      void *priv, u32 addr)
 {
-	return __rpmsg_create_ept(rpdev->vrp, rpdev, cb, priv, addr);
+	struct virtio_rpmsg_channel *vch = to_virtio_rpmsg_channel(&rpdev->dev);
+	return __rpmsg_create_ept(vch->vrp, rpdev, cb, priv, addr);
 }
 
 /**
@@ -222,12 +238,14 @@ __rpmsg_destroy_ept(struct virtproc_info *vrp, struct rpmsg_endpoint *ept)
 
 static void virtio_rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
 {
-	__rpmsg_destroy_ept(ept->rpdev->vrp, ept);
+	struct virtio_rpmsg_channel *vch = to_virtio_rpmsg_channel(&ept->rpdev->dev);
+	__rpmsg_destroy_ept(vch->vrp, ept);
 }
 
 static int virtio_rpmsg_announce_create(struct rpmsg_device *rpdev)
 {
-	struct virtproc_info *vrp = rpdev->vrp;
+	struct virtio_rpmsg_channel *vch = to_virtio_rpmsg_channel(&rpdev->dev);
+	struct virtproc_info *vrp = vch->vrp;
 	struct device *dev = &rpdev->dev;
 	int err = 0;
 
@@ -250,7 +268,8 @@ static int virtio_rpmsg_announce_create(struct rpmsg_device *rpdev)
 
 static int virtio_rpmsg_announce_destroy(struct rpmsg_device *rpdev)
 {
-	struct virtproc_info *vrp = rpdev->vrp;
+	struct virtio_rpmsg_channel *vch = to_virtio_rpmsg_channel(&rpdev->dev);
+	struct virtproc_info *vrp = vch->vrp;
 	struct device *dev = &rpdev->dev;
 	int err = 0;
 
@@ -292,7 +311,7 @@ static const struct rpmsg_channel virtio_rpmsg_ops = {
 static struct rpmsg_device *rpmsg_create_channel(struct virtproc_info *vrp,
 						 struct rpmsg_channel_info *chinfo)
 {
-	struct rpmsg_channel *rpch;
+	struct virtio_rpmsg_channel *vch;
 	struct rpmsg_device *rpdev;
 	struct device *tmp, *dev = &vrp->vdev->dev;
 	int ret;
@@ -307,15 +326,18 @@ static struct rpmsg_device *rpmsg_create_channel(struct virtproc_info *vrp,
 		return NULL;
 	}
 
-	rpch = kzalloc(sizeof(*rpch), GFP_KERNEL);
-	if (!rpch)
+	vch = kzalloc(sizeof(*vch), GFP_KERNEL);
+	if (!vch)
 		return NULL;
 
+	/* Link the channel to our vrp */
+	vch->vrp = vrp;
+
 	/* Assign callbacks for rpmsg_channel */
-	*rpch = virtio_rpmsg_ops;
+	vch->rpch = virtio_rpmsg_ops;
 
-	rpdev = &rpch->rpdev;
-	rpdev->vrp = vrp;
+	/* Assign public information to the rpmsg_device */
+	rpdev = &vch->rpch.rpdev;
 	rpdev->src = chinfo->src;
 	rpdev->dst = chinfo->dst;
 
@@ -453,7 +475,8 @@ static int rpmsg_send_offchannel_raw(struct rpmsg_device *rpdev,
 				     u32 src, u32 dst,
 				     void *data, int len, bool wait)
 {
-	struct virtproc_info *vrp = rpdev->vrp;
+	struct virtio_rpmsg_channel *vch = to_virtio_rpmsg_channel(&rpdev->dev);
+	struct virtproc_info *vrp = vch->vrp;
 	struct device *dev = &rpdev->dev;
 	struct scatterlist sg;
 	struct rpmsg_hdr *msg;
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index 3d0ff950c0d6..a5679b9b6102 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -95,7 +95,6 @@ enum rpmsg_ns_flags {
 
 #define RPMSG_ADDR_ANY		0xFFFFFFFF
 
-struct virtproc_info;
 struct rpmsg_device;
 struct rpmsg_endpoint;
 
@@ -103,7 +102,6 @@ typedef void (*rpmsg_rx_cb_t)(struct rpmsg_device *, void *, int, void *, u32);
 
 /**
  * rpmsg_device - device that belong to the rpmsg bus
- * @vrp: the remote processor this channel belongs to
  * @dev: the device struct
  * @id: device id (used to match between rpmsg drivers and devices)
  * @src: local address
@@ -112,7 +110,6 @@ typedef void (*rpmsg_rx_cb_t)(struct rpmsg_device *, void *, int, void *, u32);
  * @announce: if set, rpmsg will announce the creation/removal of this channel
  */
 struct rpmsg_device {
-	struct virtproc_info *vrp;
 	struct device dev;
 	struct rpmsg_device_id id;
 	u32 src;
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 11/14] rpmsg: Move virtio specifics from public header
  2016-08-16  0:17 ` Bjorn Andersson
@ 2016-08-16  0:17   ` Bjorn Andersson
  -1 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-16  0:17 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson
  Cc: linux-remoteproc, linux-arm-msm, linux-arm-kernel, linux-kernel

Move virtio rpmsg implementation details from the public header file to
the virtio rpmsg implementation.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/rpmsg/virtio_rpmsg_bus.c | 52 ++++++++++++++++++++++++++++++++++++++++
 include/linux/rpmsg.h            | 52 ----------------------------------------
 2 files changed, 52 insertions(+), 52 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 6ad4c657aaf4..a284b48285a1 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -75,6 +75,58 @@ struct virtproc_info {
 	struct rpmsg_endpoint *ns_ept;
 };
 
+/* The feature bitmap for virtio rpmsg */
+#define VIRTIO_RPMSG_F_NS	0 /* RP supports name service notifications */
+
+/**
+ * struct rpmsg_hdr - common header for all rpmsg messages
+ * @src: source address
+ * @dst: destination address
+ * @reserved: reserved for future use
+ * @len: length of payload (in bytes)
+ * @flags: message flags
+ * @data: @len bytes of message payload data
+ *
+ * Every message sent(/received) on the rpmsg bus begins with this header.
+ */
+struct rpmsg_hdr {
+	u32 src;
+	u32 dst;
+	u32 reserved;
+	u16 len;
+	u16 flags;
+	u8 data[0];
+} __packed;
+
+/**
+ * struct rpmsg_ns_msg - dynamic name service announcement message
+ * @name: name of remote service that is published
+ * @addr: address of remote service that is published
+ * @flags: indicates whether service is created or destroyed
+ *
+ * This message is sent across to publish a new service, or announce
+ * about its removal. When we receive these messages, an appropriate
+ * rpmsg channel (i.e device) is created/destroyed. In turn, the ->probe()
+ * or ->remove() handler of the appropriate rpmsg driver will be invoked
+ * (if/as-soon-as one is registered).
+ */
+struct rpmsg_ns_msg {
+	char name[RPMSG_NAME_SIZE];
+	u32 addr;
+	u32 flags;
+} __packed;
+
+/**
+ * enum rpmsg_ns_flags - dynamic name service announcement flags
+ *
+ * @RPMSG_NS_CREATE: a new remote service was just created
+ * @RPMSG_NS_DESTROY: a known remote service was just destroyed
+ */
+enum rpmsg_ns_flags {
+	RPMSG_NS_CREATE		= 0,
+	RPMSG_NS_DESTROY	= 1,
+};
+
 /**
  * @vrp: the remote processor this channel belongs to
  */
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index a5679b9b6102..db409a8e3178 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -41,58 +41,6 @@
 #include <linux/kref.h>
 #include <linux/mutex.h>
 
-/* The feature bitmap for virtio rpmsg */
-#define VIRTIO_RPMSG_F_NS	0 /* RP supports name service notifications */
-
-/**
- * struct rpmsg_hdr - common header for all rpmsg messages
- * @src: source address
- * @dst: destination address
- * @reserved: reserved for future use
- * @len: length of payload (in bytes)
- * @flags: message flags
- * @data: @len bytes of message payload data
- *
- * Every message sent(/received) on the rpmsg bus begins with this header.
- */
-struct rpmsg_hdr {
-	u32 src;
-	u32 dst;
-	u32 reserved;
-	u16 len;
-	u16 flags;
-	u8 data[0];
-} __packed;
-
-/**
- * struct rpmsg_ns_msg - dynamic name service announcement message
- * @name: name of remote service that is published
- * @addr: address of remote service that is published
- * @flags: indicates whether service is created or destroyed
- *
- * This message is sent across to publish a new service, or announce
- * about its removal. When we receive these messages, an appropriate
- * rpmsg channel (i.e device) is created/destroyed. In turn, the ->probe()
- * or ->remove() handler of the appropriate rpmsg driver will be invoked
- * (if/as-soon-as one is registered).
- */
-struct rpmsg_ns_msg {
-	char name[RPMSG_NAME_SIZE];
-	u32 addr;
-	u32 flags;
-} __packed;
-
-/**
- * enum rpmsg_ns_flags - dynamic name service announcement flags
- *
- * @RPMSG_NS_CREATE: a new remote service was just created
- * @RPMSG_NS_DESTROY: a known remote service was just destroyed
- */
-enum rpmsg_ns_flags {
-	RPMSG_NS_CREATE		= 0,
-	RPMSG_NS_DESTROY	= 1,
-};
-
 #define RPMSG_ADDR_ANY		0xFFFFFFFF
 
 struct rpmsg_device;
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 11/14] rpmsg: Move virtio specifics from public header
@ 2016-08-16  0:17   ` Bjorn Andersson
  0 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-16  0:17 UTC (permalink / raw)
  To: linux-arm-kernel

Move virtio rpmsg implementation details from the public header file to
the virtio rpmsg implementation.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/rpmsg/virtio_rpmsg_bus.c | 52 ++++++++++++++++++++++++++++++++++++++++
 include/linux/rpmsg.h            | 52 ----------------------------------------
 2 files changed, 52 insertions(+), 52 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 6ad4c657aaf4..a284b48285a1 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -75,6 +75,58 @@ struct virtproc_info {
 	struct rpmsg_endpoint *ns_ept;
 };
 
+/* The feature bitmap for virtio rpmsg */
+#define VIRTIO_RPMSG_F_NS	0 /* RP supports name service notifications */
+
+/**
+ * struct rpmsg_hdr - common header for all rpmsg messages
+ * @src: source address
+ * @dst: destination address
+ * @reserved: reserved for future use
+ * @len: length of payload (in bytes)
+ * @flags: message flags
+ * @data: @len bytes of message payload data
+ *
+ * Every message sent(/received) on the rpmsg bus begins with this header.
+ */
+struct rpmsg_hdr {
+	u32 src;
+	u32 dst;
+	u32 reserved;
+	u16 len;
+	u16 flags;
+	u8 data[0];
+} __packed;
+
+/**
+ * struct rpmsg_ns_msg - dynamic name service announcement message
+ * @name: name of remote service that is published
+ * @addr: address of remote service that is published
+ * @flags: indicates whether service is created or destroyed
+ *
+ * This message is sent across to publish a new service, or announce
+ * about its removal. When we receive these messages, an appropriate
+ * rpmsg channel (i.e device) is created/destroyed. In turn, the ->probe()
+ * or ->remove() handler of the appropriate rpmsg driver will be invoked
+ * (if/as-soon-as one is registered).
+ */
+struct rpmsg_ns_msg {
+	char name[RPMSG_NAME_SIZE];
+	u32 addr;
+	u32 flags;
+} __packed;
+
+/**
+ * enum rpmsg_ns_flags - dynamic name service announcement flags
+ *
+ * @RPMSG_NS_CREATE: a new remote service was just created
+ * @RPMSG_NS_DESTROY: a known remote service was just destroyed
+ */
+enum rpmsg_ns_flags {
+	RPMSG_NS_CREATE		= 0,
+	RPMSG_NS_DESTROY	= 1,
+};
+
 /**
  * @vrp: the remote processor this channel belongs to
  */
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index a5679b9b6102..db409a8e3178 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -41,58 +41,6 @@
 #include <linux/kref.h>
 #include <linux/mutex.h>
 
-/* The feature bitmap for virtio rpmsg */
-#define VIRTIO_RPMSG_F_NS	0 /* RP supports name service notifications */
-
-/**
- * struct rpmsg_hdr - common header for all rpmsg messages
- * @src: source address
- * @dst: destination address
- * @reserved: reserved for future use
- * @len: length of payload (in bytes)
- * @flags: message flags
- * @data: @len bytes of message payload data
- *
- * Every message sent(/received) on the rpmsg bus begins with this header.
- */
-struct rpmsg_hdr {
-	u32 src;
-	u32 dst;
-	u32 reserved;
-	u16 len;
-	u16 flags;
-	u8 data[0];
-} __packed;
-
-/**
- * struct rpmsg_ns_msg - dynamic name service announcement message
- * @name: name of remote service that is published
- * @addr: address of remote service that is published
- * @flags: indicates whether service is created or destroyed
- *
- * This message is sent across to publish a new service, or announce
- * about its removal. When we receive these messages, an appropriate
- * rpmsg channel (i.e device) is created/destroyed. In turn, the ->probe()
- * or ->remove() handler of the appropriate rpmsg driver will be invoked
- * (if/as-soon-as one is registered).
- */
-struct rpmsg_ns_msg {
-	char name[RPMSG_NAME_SIZE];
-	u32 addr;
-	u32 flags;
-} __packed;
-
-/**
- * enum rpmsg_ns_flags - dynamic name service announcement flags
- *
- * @RPMSG_NS_CREATE: a new remote service was just created
- * @RPMSG_NS_DESTROY: a known remote service was just destroyed
- */
-enum rpmsg_ns_flags {
-	RPMSG_NS_CREATE		= 0,
-	RPMSG_NS_DESTROY	= 1,
-};
-
 #define RPMSG_ADDR_ANY		0xFFFFFFFF
 
 struct rpmsg_device;
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 12/14] rpmsg: Make rpmsg_create_ept() take channel_info struct
  2016-08-16  0:17 ` Bjorn Andersson
@ 2016-08-16  0:17   ` Bjorn Andersson
  -1 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-16  0:17 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson
  Cc: linux-remoteproc, linux-arm-msm, linux-arm-kernel, linux-kernel

Some rpmsg backends does only support point-to-point "links" represented
by a name. By making rpmsg_create_ept() take a channel_info struct we
allow for these backends to either be passed a source address, a
destination address or a name identifier.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/rpmsg/rpmsg_core.c       | 12 +++++++++---
 drivers/rpmsg/rpmsg_internal.h   | 14 +-------------
 drivers/rpmsg/virtio_rpmsg_bus.c |  5 +++--
 include/linux/rpmsg.h            | 15 ++++++++++++++-
 4 files changed, 27 insertions(+), 19 deletions(-)

diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
index 6f7cc79f7229..54df4f77d72c 100644
--- a/drivers/rpmsg/rpmsg_core.c
+++ b/drivers/rpmsg/rpmsg_core.c
@@ -78,11 +78,12 @@
  * Returns a pointer to the endpoint on success, or NULL on error.
  */
 struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev,
-				rpmsg_rx_cb_t cb, void *priv, u32 addr)
+				rpmsg_rx_cb_t cb, void *priv,
+				struct rpmsg_channel_info chinfo)
 {
 	struct rpmsg_channel *rpch = to_rpmsg_channel(&rpdev->dev);
 
-	return rpch->create_ept(rpdev, cb, priv, addr);
+	return rpch->create_ept(rpdev, cb, priv, chinfo);
 }
 EXPORT_SYMBOL(rpmsg_create_ept);
 
@@ -337,10 +338,15 @@ static int rpmsg_dev_probe(struct device *dev)
 	struct rpmsg_channel *rpch = to_rpmsg_channel(dev);
 	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
 	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
+	struct rpmsg_channel_info chinfo = {};
 	struct rpmsg_endpoint *ept;
 	int err;
 
-	ept = rpmsg_create_ept(rpdev, rpdrv->callback, NULL, rpdev->src);
+	strncpy(chinfo.name, rpdev->id.name, RPMSG_NAME_SIZE);
+	chinfo.src = rpdev->src;
+	chinfo.dst = RPMSG_ADDR_ANY;
+
+	ept = rpmsg_create_ept(rpdev, rpdrv->callback, NULL, chinfo);
 	if (!ept) {
 		dev_err(dev, "failed to create endpoint\n");
 		err = -ENOMEM;
diff --git a/drivers/rpmsg/rpmsg_internal.h b/drivers/rpmsg/rpmsg_internal.h
index 54083bf54d14..1ac96d7ac363 100644
--- a/drivers/rpmsg/rpmsg_internal.h
+++ b/drivers/rpmsg/rpmsg_internal.h
@@ -23,24 +23,12 @@
 #define to_rpmsg_device(d) container_of(d, struct rpmsg_device, dev)
 #define to_rpmsg_driver(d) container_of(d, struct rpmsg_driver, drv)
 
-/**
- * struct rpmsg_channel_info - internal channel info representation
- * @name: name of service
- * @src: local address
- * @dst: destination address
- */
-struct rpmsg_channel_info {
-	char name[RPMSG_NAME_SIZE];
-	u32 src;
-	u32 dst;
-};
-
 struct rpmsg_channel {
 	struct rpmsg_device rpdev;
 
 	struct rpmsg_endpoint *(*create_ept)(struct rpmsg_device *rpdev,
 					     rpmsg_rx_cb_t cb, void *priv,
-					     u32 addr);
+					     struct rpmsg_channel_info chinfo);
 	void (*destroy_ept)(struct rpmsg_endpoint *ept);
 
 	int (*send)(struct rpmsg_endpoint *ept, void *data, int len);
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index a284b48285a1..d39e381bc596 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -256,10 +256,11 @@ free_ept:
 
 static struct rpmsg_endpoint *virtio_rpmsg_create_ept(struct rpmsg_device *rpdev,
 						      rpmsg_rx_cb_t cb,
-						      void *priv, u32 addr)
+						      void *priv,
+						      struct rpmsg_channel_info chinfo)
 {
 	struct virtio_rpmsg_channel *vch = to_virtio_rpmsg_channel(&rpdev->dev);
-	return __rpmsg_create_ept(vch->vrp, rpdev, cb, priv, addr);
+	return __rpmsg_create_ept(vch->vrp, rpdev, cb, priv, chinfo.src);
 }
 
 /**
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index db409a8e3178..bdd1a2285733 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -49,6 +49,18 @@ struct rpmsg_endpoint;
 typedef void (*rpmsg_rx_cb_t)(struct rpmsg_device *, void *, int, void *, u32);
 
 /**
+ * struct rpmsg_channel_info - internal channel info representation
+ * @name: name of service
+ * @src: local address
+ * @dst: destination address
+ */
+struct rpmsg_channel_info {
+	char name[RPMSG_NAME_SIZE];
+	u32 src;
+	u32 dst;
+};
+
+/**
  * rpmsg_device - device that belong to the rpmsg bus
  * @dev: the device struct
  * @id: device id (used to match between rpmsg drivers and devices)
@@ -120,7 +132,8 @@ int __register_rpmsg_driver(struct rpmsg_driver *drv, struct module *owner);
 void unregister_rpmsg_driver(struct rpmsg_driver *drv);
 void rpmsg_destroy_ept(struct rpmsg_endpoint *);
 struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *,
-					rpmsg_rx_cb_t cb, void *priv, u32 addr);
+					rpmsg_rx_cb_t cb, void *priv,
+					struct rpmsg_channel_info chinfo);
 
 /* use a macro to avoid include chaining to get THIS_MODULE */
 #define register_rpmsg_driver(drv) \
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 12/14] rpmsg: Make rpmsg_create_ept() take channel_info struct
@ 2016-08-16  0:17   ` Bjorn Andersson
  0 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-16  0:17 UTC (permalink / raw)
  To: linux-arm-kernel

Some rpmsg backends does only support point-to-point "links" represented
by a name. By making rpmsg_create_ept() take a channel_info struct we
allow for these backends to either be passed a source address, a
destination address or a name identifier.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/rpmsg/rpmsg_core.c       | 12 +++++++++---
 drivers/rpmsg/rpmsg_internal.h   | 14 +-------------
 drivers/rpmsg/virtio_rpmsg_bus.c |  5 +++--
 include/linux/rpmsg.h            | 15 ++++++++++++++-
 4 files changed, 27 insertions(+), 19 deletions(-)

diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
index 6f7cc79f7229..54df4f77d72c 100644
--- a/drivers/rpmsg/rpmsg_core.c
+++ b/drivers/rpmsg/rpmsg_core.c
@@ -78,11 +78,12 @@
  * Returns a pointer to the endpoint on success, or NULL on error.
  */
 struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev,
-				rpmsg_rx_cb_t cb, void *priv, u32 addr)
+				rpmsg_rx_cb_t cb, void *priv,
+				struct rpmsg_channel_info chinfo)
 {
 	struct rpmsg_channel *rpch = to_rpmsg_channel(&rpdev->dev);
 
-	return rpch->create_ept(rpdev, cb, priv, addr);
+	return rpch->create_ept(rpdev, cb, priv, chinfo);
 }
 EXPORT_SYMBOL(rpmsg_create_ept);
 
@@ -337,10 +338,15 @@ static int rpmsg_dev_probe(struct device *dev)
 	struct rpmsg_channel *rpch = to_rpmsg_channel(dev);
 	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
 	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
+	struct rpmsg_channel_info chinfo = {};
 	struct rpmsg_endpoint *ept;
 	int err;
 
-	ept = rpmsg_create_ept(rpdev, rpdrv->callback, NULL, rpdev->src);
+	strncpy(chinfo.name, rpdev->id.name, RPMSG_NAME_SIZE);
+	chinfo.src = rpdev->src;
+	chinfo.dst = RPMSG_ADDR_ANY;
+
+	ept = rpmsg_create_ept(rpdev, rpdrv->callback, NULL, chinfo);
 	if (!ept) {
 		dev_err(dev, "failed to create endpoint\n");
 		err = -ENOMEM;
diff --git a/drivers/rpmsg/rpmsg_internal.h b/drivers/rpmsg/rpmsg_internal.h
index 54083bf54d14..1ac96d7ac363 100644
--- a/drivers/rpmsg/rpmsg_internal.h
+++ b/drivers/rpmsg/rpmsg_internal.h
@@ -23,24 +23,12 @@
 #define to_rpmsg_device(d) container_of(d, struct rpmsg_device, dev)
 #define to_rpmsg_driver(d) container_of(d, struct rpmsg_driver, drv)
 
-/**
- * struct rpmsg_channel_info - internal channel info representation
- * @name: name of service
- * @src: local address
- * @dst: destination address
- */
-struct rpmsg_channel_info {
-	char name[RPMSG_NAME_SIZE];
-	u32 src;
-	u32 dst;
-};
-
 struct rpmsg_channel {
 	struct rpmsg_device rpdev;
 
 	struct rpmsg_endpoint *(*create_ept)(struct rpmsg_device *rpdev,
 					     rpmsg_rx_cb_t cb, void *priv,
-					     u32 addr);
+					     struct rpmsg_channel_info chinfo);
 	void (*destroy_ept)(struct rpmsg_endpoint *ept);
 
 	int (*send)(struct rpmsg_endpoint *ept, void *data, int len);
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index a284b48285a1..d39e381bc596 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -256,10 +256,11 @@ free_ept:
 
 static struct rpmsg_endpoint *virtio_rpmsg_create_ept(struct rpmsg_device *rpdev,
 						      rpmsg_rx_cb_t cb,
-						      void *priv, u32 addr)
+						      void *priv,
+						      struct rpmsg_channel_info chinfo)
 {
 	struct virtio_rpmsg_channel *vch = to_virtio_rpmsg_channel(&rpdev->dev);
-	return __rpmsg_create_ept(vch->vrp, rpdev, cb, priv, addr);
+	return __rpmsg_create_ept(vch->vrp, rpdev, cb, priv, chinfo.src);
 }
 
 /**
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index db409a8e3178..bdd1a2285733 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -49,6 +49,18 @@ struct rpmsg_endpoint;
 typedef void (*rpmsg_rx_cb_t)(struct rpmsg_device *, void *, int, void *, u32);
 
 /**
+ * struct rpmsg_channel_info - internal channel info representation
+ * @name: name of service
+ * @src: local address
+ * @dst: destination address
+ */
+struct rpmsg_channel_info {
+	char name[RPMSG_NAME_SIZE];
+	u32 src;
+	u32 dst;
+};
+
+/**
  * rpmsg_device - device that belong to the rpmsg bus
  * @dev: the device struct
  * @id: device id (used to match between rpmsg drivers and devices)
@@ -120,7 +132,8 @@ int __register_rpmsg_driver(struct rpmsg_driver *drv, struct module *owner);
 void unregister_rpmsg_driver(struct rpmsg_driver *drv);
 void rpmsg_destroy_ept(struct rpmsg_endpoint *);
 struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *,
-					rpmsg_rx_cb_t cb, void *priv, u32 addr);
+					rpmsg_rx_cb_t cb, void *priv,
+					struct rpmsg_channel_info chinfo);
 
 /* use a macro to avoid include chaining to get THIS_MODULE */
 #define register_rpmsg_driver(drv) \
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 13/14] rpmsg: Allow callback to return errors
  2016-08-16  0:17 ` Bjorn Andersson
@ 2016-08-16  0:17   ` Bjorn Andersson
  -1 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-16  0:17 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson
  Cc: linux-remoteproc, linux-arm-msm, linux-arm-kernel, linux-kernel

Some rpmsg backends support holding on to and redelivering messages upon
failed handling of them, so provide a way for the callback to report and
error and allow the backends to handle this.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/rpmsg/virtio_rpmsg_bus.c | 10 ++++++----
 include/linux/rpmsg.h            |  4 ++--
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index d39e381bc596..9d681d68f7f3 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -785,8 +785,8 @@ static void rpmsg_xmit_done(struct virtqueue *svq)
 }
 
 /* invoked when a name service announcement arrives */
-static void rpmsg_ns_cb(struct rpmsg_device *rpdev, void *data, int len,
-			void *priv, u32 src)
+static int rpmsg_ns_cb(struct rpmsg_device *rpdev, void *data, int len,
+		       void *priv, u32 src)
 {
 	struct rpmsg_ns_msg *msg = data;
 	struct rpmsg_device *newch;
@@ -802,7 +802,7 @@ static void rpmsg_ns_cb(struct rpmsg_device *rpdev, void *data, int len,
 
 	if (len != sizeof(*msg)) {
 		dev_err(dev, "malformed ns msg (%d)\n", len);
-		return;
+		return -EINVAL;
 	}
 
 	/*
@@ -813,7 +813,7 @@ static void rpmsg_ns_cb(struct rpmsg_device *rpdev, void *data, int len,
 	 */
 	if (rpdev) {
 		dev_err(dev, "anomaly: ns ept has an rpdev handle\n");
-		return;
+		return -EINVAL;
 	}
 
 	/* don't trust the remote processor for null terminating the name */
@@ -836,6 +836,8 @@ static void rpmsg_ns_cb(struct rpmsg_device *rpdev, void *data, int len,
 		if (!newch)
 			dev_err(dev, "rpmsg_create_channel failed\n");
 	}
+
+	return 0;
 }
 
 static int rpmsg_probe(struct virtio_device *vdev)
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index bdd1a2285733..19213e660a9b 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -46,7 +46,7 @@
 struct rpmsg_device;
 struct rpmsg_endpoint;
 
-typedef void (*rpmsg_rx_cb_t)(struct rpmsg_device *, void *, int, void *, u32);
+typedef int (*rpmsg_rx_cb_t)(struct rpmsg_device *, void *, int, void *, u32);
 
 /**
  * struct rpmsg_channel_info - internal channel info representation
@@ -123,7 +123,7 @@ struct rpmsg_driver {
 	const struct rpmsg_device_id *id_table;
 	int (*probe)(struct rpmsg_device *dev);
 	void (*remove)(struct rpmsg_device *dev);
-	void (*callback)(struct rpmsg_device *, void *, int, void *, u32);
+	int (*callback)(struct rpmsg_device *, void *, int, void *, u32);
 };
 
 int register_rpmsg_device(struct rpmsg_device *dev);
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 13/14] rpmsg: Allow callback to return errors
@ 2016-08-16  0:17   ` Bjorn Andersson
  0 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-16  0:17 UTC (permalink / raw)
  To: linux-arm-kernel

Some rpmsg backends support holding on to and redelivering messages upon
failed handling of them, so provide a way for the callback to report and
error and allow the backends to handle this.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
 drivers/rpmsg/virtio_rpmsg_bus.c | 10 ++++++----
 include/linux/rpmsg.h            |  4 ++--
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index d39e381bc596..9d681d68f7f3 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -785,8 +785,8 @@ static void rpmsg_xmit_done(struct virtqueue *svq)
 }
 
 /* invoked when a name service announcement arrives */
-static void rpmsg_ns_cb(struct rpmsg_device *rpdev, void *data, int len,
-			void *priv, u32 src)
+static int rpmsg_ns_cb(struct rpmsg_device *rpdev, void *data, int len,
+		       void *priv, u32 src)
 {
 	struct rpmsg_ns_msg *msg = data;
 	struct rpmsg_device *newch;
@@ -802,7 +802,7 @@ static void rpmsg_ns_cb(struct rpmsg_device *rpdev, void *data, int len,
 
 	if (len != sizeof(*msg)) {
 		dev_err(dev, "malformed ns msg (%d)\n", len);
-		return;
+		return -EINVAL;
 	}
 
 	/*
@@ -813,7 +813,7 @@ static void rpmsg_ns_cb(struct rpmsg_device *rpdev, void *data, int len,
 	 */
 	if (rpdev) {
 		dev_err(dev, "anomaly: ns ept has an rpdev handle\n");
-		return;
+		return -EINVAL;
 	}
 
 	/* don't trust the remote processor for null terminating the name */
@@ -836,6 +836,8 @@ static void rpmsg_ns_cb(struct rpmsg_device *rpdev, void *data, int len,
 		if (!newch)
 			dev_err(dev, "rpmsg_create_channel failed\n");
 	}
+
+	return 0;
 }
 
 static int rpmsg_probe(struct virtio_device *vdev)
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index bdd1a2285733..19213e660a9b 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -46,7 +46,7 @@
 struct rpmsg_device;
 struct rpmsg_endpoint;
 
-typedef void (*rpmsg_rx_cb_t)(struct rpmsg_device *, void *, int, void *, u32);
+typedef int (*rpmsg_rx_cb_t)(struct rpmsg_device *, void *, int, void *, u32);
 
 /**
  * struct rpmsg_channel_info - internal channel info representation
@@ -123,7 +123,7 @@ struct rpmsg_driver {
 	const struct rpmsg_device_id *id_table;
 	int (*probe)(struct rpmsg_device *dev);
 	void (*remove)(struct rpmsg_device *dev);
-	void (*callback)(struct rpmsg_device *, void *, int, void *, u32);
+	int (*callback)(struct rpmsg_device *, void *, int, void *, u32);
 };
 
 int register_rpmsg_device(struct rpmsg_device *dev);
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 14/14] rpmsg: Introduce Qualcomm SMD backend
  2016-08-16  0:17 ` Bjorn Andersson
@ 2016-08-16  0:17   ` Bjorn Andersson
  -1 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-16  0:17 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson
  Cc: linux-remoteproc, linux-arm-msm, linux-arm-kernel, linux-kernel,
	Sricharan R

This introduces a new rpmsg backend for the Qualcomm SMD system,
allowing communication with various remote processors found in Qualcomm
platforms. The implementation is based on, and intends to replace,
drivers/soc/qcom/smd.c with the necessary adaptions for fitting with the
rpmsg core.

Based on original work by Sricharan R <sricharan@codeaurora.org>

Cc: Sricharan R <sricharan@codeaurora.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---

I've been unable to find a feasible way to migrate the existing SMD
implementation, so instead this is based on a copy of the current SMD
implementation. With this in place the drivers can be transitioned in one go
and the old implementation can be dropped.

 drivers/rpmsg/Kconfig    |   10 +
 drivers/rpmsg/Makefile   |    1 +
 drivers/rpmsg/qcom_smd.c | 1448 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 1459 insertions(+)
 create mode 100644 drivers/rpmsg/qcom_smd.c

diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig
index 40614be88c97..bdbec8124d8f 100644
--- a/drivers/rpmsg/Kconfig
+++ b/drivers/rpmsg/Kconfig
@@ -10,4 +10,14 @@ config RPMSG_VIRTIO
 	select VIRTIO
 	select VIRTUALIZATION
 
+config RPMSG_QCOM_SMD
+	tristate "Qualcomm Shared Memory Driver (SMD)"
+	depends on QCOM_SMEM
+	depends on !QCOM_SMD
+	select RPMSG
+	help
+	  Say y here to enable support for the Qualcomm Shared Memory Driver
+	  providing communication channels to remote processors in Qualcomm
+	  platforms.
+
 endmenu
diff --git a/drivers/rpmsg/Makefile b/drivers/rpmsg/Makefile
index 383213417a00..eb5211efedc4 100644
--- a/drivers/rpmsg/Makefile
+++ b/drivers/rpmsg/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_RPMSG)	+= rpmsg_core.o
 obj-$(CONFIG_RPMSG_VIRTIO) += virtio_rpmsg_bus.o
+obj-$(CONFIG_RPMSG_QCOM_SMD) += qcom_smd.o
diff --git a/drivers/rpmsg/qcom_smd.c b/drivers/rpmsg/qcom_smd.c
new file mode 100644
index 000000000000..eff87ac954e7
--- /dev/null
+++ b/drivers/rpmsg/qcom_smd.c
@@ -0,0 +1,1448 @@
+/*
+ * Copyright (c) 2015, Sony Mobile Communications AB.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/soc/qcom/smem.h>
+#include <linux/wait.h>
+#include <linux/rpmsg.h>
+
+#include "rpmsg_internal.h"
+
+/*
+ * The Qualcomm Shared Memory communication solution provides point-to-point
+ * channels for clients to send and receive streaming or packet based data.
+ *
+ * Each channel consists of a control item (channel info) and a ring buffer
+ * pair. The channel info carry information related to channel state, flow
+ * control and the offsets within the ring buffer.
+ *
+ * All allocated channels are listed in an allocation table, identifying the
+ * pair of items by name, type and remote processor.
+ *
+ * Upon creating a new channel the remote processor allocates channel info and
+ * ring buffer items from the smem heap and populate the allocation table. An
+ * interrupt is sent to the other end of the channel and a scan for new
+ * channels should be done. A channel never goes away, it will only change
+ * state.
+ *
+ * The remote processor signals it intent for bring up the communication
+ * channel by setting the state of its end of the channel to "opening" and
+ * sends out an interrupt. We detect this change and register a smd device to
+ * consume the channel. Upon finding a consumer we finish the handshake and the
+ * channel is up.
+ *
+ * Upon closing a channel, the remote processor will update the state of its
+ * end of the channel and signal us, we will then unregister any attached
+ * device and close our end of the channel.
+ *
+ * Devices attached to a channel can use the qcom_smd_send function to push
+ * data to the channel, this is done by copying the data into the tx ring
+ * buffer, updating the pointers in the channel info and signaling the remote
+ * processor.
+ *
+ * The remote processor does the equivalent when it transfer data and upon
+ * receiving the interrupt we check the channel info for new data and delivers
+ * this to the attached device. If the device is not ready to receive the data
+ * we leave it in the ring buffer for now.
+ */
+
+struct smd_channel_info;
+struct smd_channel_info_pair;
+struct smd_channel_info_word;
+struct smd_channel_info_word_pair;
+
+#define SMD_ALLOC_TBL_COUNT	2
+#define SMD_ALLOC_TBL_SIZE	64
+
+/*
+ * This lists the various smem heap items relevant for the allocation table and
+ * smd channel entries.
+ */
+static const struct {
+	unsigned alloc_tbl_id;
+	unsigned info_base_id;
+	unsigned fifo_base_id;
+} smem_items[SMD_ALLOC_TBL_COUNT] = {
+	{
+		.alloc_tbl_id = 13,
+		.info_base_id = 14,
+		.fifo_base_id = 338
+	},
+	{
+		.alloc_tbl_id = 266,
+		.info_base_id = 138,
+		.fifo_base_id = 202,
+	},
+};
+
+/**
+ * struct qcom_smd_edge - representing a remote processor
+ * @of_node:		of_node handle for information related to this edge
+ * @edge_id:		identifier of this edge
+ * @remote_pid:		identifier of remote processor
+ * @irq:		interrupt for signals on this edge
+ * @ipc_regmap:		regmap handle holding the outgoing ipc register
+ * @ipc_offset:		offset within @ipc_regmap of the register for ipc
+ * @ipc_bit:		bit in the register at @ipc_offset of @ipc_regmap
+ * @channels:		list of all channels detected on this edge
+ * @channels_lock:	guard for modifications of @channels
+ * @allocated:		array of bitmaps representing already allocated channels
+ * @smem_available:	last available amount of smem triggering a channel scan
+ * @scan_work:		work item for discovering new channels
+ * @state_work:		work item for edge state changes
+ */
+struct qcom_smd_edge {
+	struct device dev;
+
+	struct device_node *of_node;
+	unsigned edge_id;
+	unsigned remote_pid;
+
+	int irq;
+
+	struct regmap *ipc_regmap;
+	int ipc_offset;
+	int ipc_bit;
+
+	struct list_head channels;
+	spinlock_t channels_lock;
+
+	DECLARE_BITMAP(allocated[SMD_ALLOC_TBL_COUNT], SMD_ALLOC_TBL_SIZE);
+
+	unsigned smem_available;
+
+	wait_queue_head_t new_channel_event;
+
+	struct work_struct scan_work;
+	struct work_struct state_work;
+};
+
+/*
+ * SMD channel states.
+ */
+enum smd_channel_state {
+	SMD_CHANNEL_CLOSED,
+	SMD_CHANNEL_OPENING,
+	SMD_CHANNEL_OPENED,
+	SMD_CHANNEL_FLUSHING,
+	SMD_CHANNEL_CLOSING,
+	SMD_CHANNEL_RESET,
+	SMD_CHANNEL_RESET_OPENING
+};
+
+struct qcom_smd_device {
+	struct rpmsg_channel rpch;
+
+	struct qcom_smd_edge *edge;
+};
+
+static inline struct qcom_smd_device *to_smd_device(struct device *d)
+{
+	struct rpmsg_channel *rpch = to_rpmsg_channel(d);
+
+	return container_of(rpch, struct qcom_smd_device, rpch);
+}
+
+struct qcom_smd_endpoint {
+	struct rpmsg_endpoint ept;
+
+	struct qcom_smd_channel *qsch;
+};
+
+#define to_smd_edge(d) container_of(d, struct qcom_smd_edge, dev)
+#define to_smd_endpoint(ept) container_of(ept, struct qcom_smd_endpoint, ept)
+
+/**
+ * struct qcom_smd_channel - smd channel struct
+ * @edge:		qcom_smd_edge this channel is living on
+ * @qsdev:		reference to a associated smd client device
+ * @name:		name of the channel
+ * @state:		local state of the channel
+ * @remote_state:	remote state of the channel
+ * @info:		byte aligned outgoing/incoming channel info
+ * @info_word:		word aligned outgoing/incoming channel info
+ * @tx_lock:		lock to make writes to the channel mutually exclusive
+ * @fblockread_event:	wakeup event tied to tx fBLOCKREADINTR
+ * @tx_fifo:		pointer to the outgoing ring buffer
+ * @rx_fifo:		pointer to the incoming ring buffer
+ * @fifo_size:		size of each ring buffer
+ * @bounce_buffer:	bounce buffer for reading wrapped packets
+ * @cb:			callback function registered for this channel
+ * @recv_lock:		guard for rx info modifications and cb pointer
+ * @pkt_size:		size of the currently handled packet
+ * @list:		lite entry for @channels in qcom_smd_edge
+ */
+struct qcom_smd_channel {
+	struct qcom_smd_edge *edge;
+
+	struct qcom_smd_endpoint *qsept;
+	bool registered;
+
+	char *name;
+	enum smd_channel_state state;
+	enum smd_channel_state remote_state;
+
+	struct smd_channel_info_pair *info;
+	struct smd_channel_info_word_pair *info_word;
+
+	struct mutex tx_lock;
+	wait_queue_head_t fblockread_event;
+
+	void *tx_fifo;
+	void *rx_fifo;
+	int fifo_size;
+
+	void *bounce_buffer;
+
+	spinlock_t recv_lock;
+
+	int pkt_size;
+
+	void *drvdata;
+
+	struct list_head list;
+};
+
+/*
+ * Format of the smd_info smem items, for byte aligned channels.
+ */
+struct smd_channel_info {
+	__le32 state;
+	u8  fDSR;
+	u8  fCTS;
+	u8  fCD;
+	u8  fRI;
+	u8  fHEAD;
+	u8  fTAIL;
+	u8  fSTATE;
+	u8  fBLOCKREADINTR;
+	__le32 tail;
+	__le32 head;
+};
+
+struct smd_channel_info_pair {
+	struct smd_channel_info tx;
+	struct smd_channel_info rx;
+};
+
+/*
+ * Format of the smd_info smem items, for word aligned channels.
+ */
+struct smd_channel_info_word {
+	__le32 state;
+	__le32 fDSR;
+	__le32 fCTS;
+	__le32 fCD;
+	__le32 fRI;
+	__le32 fHEAD;
+	__le32 fTAIL;
+	__le32 fSTATE;
+	__le32 fBLOCKREADINTR;
+	__le32 tail;
+	__le32 head;
+};
+
+struct smd_channel_info_word_pair {
+	struct smd_channel_info_word tx;
+	struct smd_channel_info_word rx;
+};
+
+#define GET_RX_CHANNEL_FLAG(channel, param)				     \
+	({								     \
+		BUILD_BUG_ON(sizeof(channel->info->rx.param) != sizeof(u8)); \
+		channel->info_word ?					     \
+			le32_to_cpu(channel->info_word->rx.param) :	     \
+			channel->info->rx.param;			     \
+	})
+
+#define GET_RX_CHANNEL_INFO(channel, param)				      \
+	({								      \
+		BUILD_BUG_ON(sizeof(channel->info->rx.param) != sizeof(u32)); \
+		le32_to_cpu(channel->info_word ?			      \
+			channel->info_word->rx.param :			      \
+			channel->info->rx.param);			      \
+	})
+
+#define SET_RX_CHANNEL_FLAG(channel, param, value)			     \
+	({								     \
+		BUILD_BUG_ON(sizeof(channel->info->rx.param) != sizeof(u8)); \
+		if (channel->info_word)					     \
+			channel->info_word->rx.param = cpu_to_le32(value);   \
+		else							     \
+			channel->info->rx.param = value;		     \
+	})
+
+#define SET_RX_CHANNEL_INFO(channel, param, value)			      \
+	({								      \
+		BUILD_BUG_ON(sizeof(channel->info->rx.param) != sizeof(u32)); \
+		if (channel->info_word)					      \
+			channel->info_word->rx.param = cpu_to_le32(value);    \
+		else							      \
+			channel->info->rx.param = cpu_to_le32(value);	      \
+	})
+
+#define GET_TX_CHANNEL_FLAG(channel, param)				     \
+	({								     \
+		BUILD_BUG_ON(sizeof(channel->info->tx.param) != sizeof(u8)); \
+		channel->info_word ?					     \
+			le32_to_cpu(channel->info_word->tx.param) :          \
+			channel->info->tx.param;			     \
+	})
+
+#define GET_TX_CHANNEL_INFO(channel, param)				      \
+	({								      \
+		BUILD_BUG_ON(sizeof(channel->info->tx.param) != sizeof(u32)); \
+		le32_to_cpu(channel->info_word ?			      \
+			channel->info_word->tx.param :			      \
+			channel->info->tx.param);			      \
+	})
+
+#define SET_TX_CHANNEL_FLAG(channel, param, value)			     \
+	({								     \
+		BUILD_BUG_ON(sizeof(channel->info->tx.param) != sizeof(u8)); \
+		if (channel->info_word)					     \
+			channel->info_word->tx.param = cpu_to_le32(value);   \
+		else							     \
+			channel->info->tx.param = value;		     \
+	})
+
+#define SET_TX_CHANNEL_INFO(channel, param, value)			      \
+	({								      \
+		BUILD_BUG_ON(sizeof(channel->info->tx.param) != sizeof(u32)); \
+		if (channel->info_word)					      \
+			channel->info_word->tx.param = cpu_to_le32(value);   \
+		else							      \
+			channel->info->tx.param = cpu_to_le32(value);	      \
+	})
+
+/**
+ * struct qcom_smd_alloc_entry - channel allocation entry
+ * @name:	channel name
+ * @cid:	channel index
+ * @flags:	channel flags and edge id
+ * @ref_count:	reference count of the channel
+ */
+struct qcom_smd_alloc_entry {
+	u8 name[20];
+	__le32 cid;
+	__le32 flags;
+	__le32 ref_count;
+} __packed;
+
+#define SMD_CHANNEL_FLAGS_EDGE_MASK	0xff
+#define SMD_CHANNEL_FLAGS_STREAM	BIT(8)
+#define SMD_CHANNEL_FLAGS_PACKET	BIT(9)
+
+/*
+ * Each smd packet contains a 20 byte header, with the first 4 being the length
+ * of the packet.
+ */
+#define SMD_PACKET_HEADER_LEN	20
+
+/*
+ * Signal the remote processor associated with 'channel'.
+ */
+static void qcom_smd_signal_channel(struct qcom_smd_channel *channel)
+{
+	struct qcom_smd_edge *edge = channel->edge;
+
+	regmap_write(edge->ipc_regmap, edge->ipc_offset, BIT(edge->ipc_bit));
+}
+
+/*
+ * Initialize the tx channel info
+ */
+static void qcom_smd_channel_reset(struct qcom_smd_channel *channel)
+{
+	SET_TX_CHANNEL_INFO(channel, state, SMD_CHANNEL_CLOSED);
+	SET_TX_CHANNEL_FLAG(channel, fDSR, 0);
+	SET_TX_CHANNEL_FLAG(channel, fCTS, 0);
+	SET_TX_CHANNEL_FLAG(channel, fCD, 0);
+	SET_TX_CHANNEL_FLAG(channel, fRI, 0);
+	SET_TX_CHANNEL_FLAG(channel, fHEAD, 0);
+	SET_TX_CHANNEL_FLAG(channel, fTAIL, 0);
+	SET_TX_CHANNEL_FLAG(channel, fSTATE, 1);
+	SET_TX_CHANNEL_FLAG(channel, fBLOCKREADINTR, 1);
+	SET_TX_CHANNEL_INFO(channel, head, 0);
+	SET_TX_CHANNEL_INFO(channel, tail, 0);
+
+	qcom_smd_signal_channel(channel);
+
+	channel->state = SMD_CHANNEL_CLOSED;
+	channel->pkt_size = 0;
+}
+
+/*
+ * Set the callback for a channel, with appropriate locking
+ */
+static void qcom_smd_channel_set_callback(struct qcom_smd_channel *channel,
+					  rpmsg_rx_cb_t cb)
+{
+	struct rpmsg_endpoint *ept = &channel->qsept->ept;
+	unsigned long flags;
+
+	spin_lock_irqsave(&channel->recv_lock, flags);
+	ept->cb = cb;
+	spin_unlock_irqrestore(&channel->recv_lock, flags);
+};
+
+/*
+ * Calculate the amount of data available in the rx fifo
+ */
+static size_t qcom_smd_channel_get_rx_avail(struct qcom_smd_channel *channel)
+{
+	unsigned head;
+	unsigned tail;
+
+	head = GET_RX_CHANNEL_INFO(channel, head);
+	tail = GET_RX_CHANNEL_INFO(channel, tail);
+
+	return (head - tail) & (channel->fifo_size - 1);
+}
+
+/*
+ * Set tx channel state and inform the remote processor
+ */
+static void qcom_smd_channel_set_state(struct qcom_smd_channel *channel,
+				       int state)
+{
+	struct qcom_smd_edge *edge = channel->edge;
+	bool is_open = state == SMD_CHANNEL_OPENED;
+
+	if (channel->state == state)
+		return;
+
+	dev_dbg(&edge->dev, "set_state(%s, %d)\n", channel->name, state);
+
+	SET_TX_CHANNEL_FLAG(channel, fDSR, is_open);
+	SET_TX_CHANNEL_FLAG(channel, fCTS, is_open);
+	SET_TX_CHANNEL_FLAG(channel, fCD, is_open);
+
+	SET_TX_CHANNEL_INFO(channel, state, state);
+	SET_TX_CHANNEL_FLAG(channel, fSTATE, 1);
+
+	channel->state = state;
+	qcom_smd_signal_channel(channel);
+}
+
+/*
+ * Copy count bytes of data using 32bit accesses, if that's required.
+ */
+static void smd_copy_to_fifo(void __iomem *dst,
+			     const void *src,
+			     size_t count,
+			     bool word_aligned)
+{
+	if (word_aligned) {
+		__iowrite32_copy(dst, src, count / sizeof(u32));
+	} else {
+		memcpy_toio(dst, src, count);
+	}
+}
+
+/*
+ * Copy count bytes of data using 32bit accesses, if that is required.
+ */
+static void smd_copy_from_fifo(void *dst,
+			       const void __iomem *src,
+			       size_t count,
+			       bool word_aligned)
+{
+	if (word_aligned) {
+		__ioread32_copy(dst, src, count / sizeof(u32));
+	} else {
+		memcpy_fromio(dst, src, count);
+	}
+}
+
+/*
+ * Read count bytes of data from the rx fifo into buf, but don't advance the
+ * tail.
+ */
+static size_t qcom_smd_channel_peek(struct qcom_smd_channel *channel,
+				    void *buf, size_t count)
+{
+	bool word_aligned;
+	unsigned tail;
+	size_t len;
+
+	word_aligned = channel->info_word;
+	tail = GET_RX_CHANNEL_INFO(channel, tail);
+
+	len = min_t(size_t, count, channel->fifo_size - tail);
+	if (len) {
+		smd_copy_from_fifo(buf,
+				   channel->rx_fifo + tail,
+				   len,
+				   word_aligned);
+	}
+
+	if (len != count) {
+		smd_copy_from_fifo(buf + len,
+				   channel->rx_fifo,
+				   count - len,
+				   word_aligned);
+	}
+
+	return count;
+}
+
+/*
+ * Advance the rx tail by count bytes.
+ */
+static void qcom_smd_channel_advance(struct qcom_smd_channel *channel,
+				     size_t count)
+{
+	unsigned tail;
+
+	tail = GET_RX_CHANNEL_INFO(channel, tail);
+	tail += count;
+	tail &= (channel->fifo_size - 1);
+	SET_RX_CHANNEL_INFO(channel, tail, tail);
+}
+
+/*
+ * Read out a single packet from the rx fifo and deliver it to the device
+ */
+static int qcom_smd_channel_recv_single(struct qcom_smd_channel *channel)
+{
+	struct rpmsg_endpoint *ept = &channel->qsept->ept;
+	unsigned tail;
+	size_t len;
+	void *ptr;
+	int ret;
+
+	tail = GET_RX_CHANNEL_INFO(channel, tail);
+
+	/* Use bounce buffer if the data wraps */
+	if (tail + channel->pkt_size >= channel->fifo_size) {
+		ptr = channel->bounce_buffer;
+		len = qcom_smd_channel_peek(channel, ptr, channel->pkt_size);
+	} else {
+		ptr = channel->rx_fifo + tail;
+		len = channel->pkt_size;
+	}
+
+	ret = ept->cb(ept->rpdev, ptr, len, ept->priv, RPMSG_ADDR_ANY);
+	if (ret < 0)
+		return ret;
+
+	/* Only forward the tail if the client consumed the data */
+	qcom_smd_channel_advance(channel, len);
+
+	channel->pkt_size = 0;
+
+	return 0;
+}
+
+/*
+ * Per channel interrupt handling
+ */
+static bool qcom_smd_channel_intr(struct qcom_smd_channel *channel)
+{
+	bool need_state_scan = false;
+	int remote_state;
+	__le32 pktlen;
+	int avail;
+	int ret;
+
+	/* Handle state changes */
+	remote_state = GET_RX_CHANNEL_INFO(channel, state);
+	if (remote_state != channel->remote_state) {
+		channel->remote_state = remote_state;
+		need_state_scan = true;
+	}
+	/* Indicate that we have seen any state change */
+	SET_RX_CHANNEL_FLAG(channel, fSTATE, 0);
+
+	/* Signal waiting qcom_smd_send() about the interrupt */
+	if (!GET_TX_CHANNEL_FLAG(channel, fBLOCKREADINTR))
+		wake_up_interruptible(&channel->fblockread_event);
+
+	/* Don't consume any data until we've opened the channel */
+	if (channel->state != SMD_CHANNEL_OPENED)
+		goto out;
+
+	/* Indicate that we've seen the new data */
+	SET_RX_CHANNEL_FLAG(channel, fHEAD, 0);
+
+	/* Consume data */
+	for (;;) {
+		avail = qcom_smd_channel_get_rx_avail(channel);
+
+		if (!channel->pkt_size && avail >= SMD_PACKET_HEADER_LEN) {
+			qcom_smd_channel_peek(channel, &pktlen, sizeof(pktlen));
+			qcom_smd_channel_advance(channel, SMD_PACKET_HEADER_LEN);
+			channel->pkt_size = le32_to_cpu(pktlen);
+		} else if (channel->pkt_size && avail >= channel->pkt_size) {
+			ret = qcom_smd_channel_recv_single(channel);
+			if (ret)
+				break;
+		} else {
+			break;
+		}
+	}
+
+	/* Indicate that we have seen and updated tail */
+	SET_RX_CHANNEL_FLAG(channel, fTAIL, 1);
+
+	/* Signal the remote that we've consumed the data (if requested) */
+	if (!GET_RX_CHANNEL_FLAG(channel, fBLOCKREADINTR)) {
+		/* Ensure ordering of channel info updates */
+		wmb();
+
+		qcom_smd_signal_channel(channel);
+	}
+
+out:
+	return need_state_scan;
+}
+
+/*
+ * The edge interrupts are triggered by the remote processor on state changes,
+ * channel info updates or when new channels are created.
+ */
+static irqreturn_t qcom_smd_edge_intr(int irq, void *data)
+{
+	struct qcom_smd_edge *edge = data;
+	struct qcom_smd_channel *channel;
+	unsigned available;
+	bool kick_scanner = false;
+	bool kick_state = false;
+
+	/*
+	 * Handle state changes or data on each of the channels on this edge
+	 */
+	spin_lock(&edge->channels_lock);
+	list_for_each_entry(channel, &edge->channels, list) {
+		spin_lock(&channel->recv_lock);
+		kick_state |= qcom_smd_channel_intr(channel);
+		spin_unlock(&channel->recv_lock);
+	}
+	spin_unlock(&edge->channels_lock);
+
+	/*
+	 * Creating a new channel requires allocating an smem entry, so we only
+	 * have to scan if the amount of available space in smem have changed
+	 * since last scan.
+	 */
+	available = qcom_smem_get_free_space(edge->remote_pid);
+	if (available != edge->smem_available) {
+		edge->smem_available = available;
+		kick_scanner = true;
+	}
+
+	if (kick_scanner)
+		schedule_work(&edge->scan_work);
+	if (kick_state)
+		schedule_work(&edge->state_work);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * Delivers any outstanding packets in the rx fifo, can be used after probe of
+ * the clients to deliver any packets that wasn't delivered before the client
+ * was setup.
+ */
+static void qcom_smd_channel_resume(struct qcom_smd_channel *channel)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&channel->recv_lock, flags);
+	qcom_smd_channel_intr(channel);
+	spin_unlock_irqrestore(&channel->recv_lock, flags);
+}
+
+/*
+ * Calculate how much space is available in the tx fifo.
+ */
+static size_t qcom_smd_get_tx_avail(struct qcom_smd_channel *channel)
+{
+	unsigned head;
+	unsigned tail;
+	unsigned mask = channel->fifo_size - 1;
+
+	head = GET_TX_CHANNEL_INFO(channel, head);
+	tail = GET_TX_CHANNEL_INFO(channel, tail);
+
+	return mask - ((head - tail) & mask);
+}
+
+/*
+ * Write count bytes of data into channel, possibly wrapping in the ring buffer
+ */
+static int qcom_smd_write_fifo(struct qcom_smd_channel *channel,
+			       const void *data,
+			       size_t count)
+{
+	bool word_aligned;
+	unsigned head;
+	size_t len;
+
+	word_aligned = channel->info_word;
+	head = GET_TX_CHANNEL_INFO(channel, head);
+
+	len = min_t(size_t, count, channel->fifo_size - head);
+	if (len) {
+		smd_copy_to_fifo(channel->tx_fifo + head,
+				 data,
+				 len,
+				 word_aligned);
+	}
+
+	if (len != count) {
+		smd_copy_to_fifo(channel->tx_fifo,
+				 data + len,
+				 count - len,
+				 word_aligned);
+	}
+
+	head += count;
+	head &= (channel->fifo_size - 1);
+	SET_TX_CHANNEL_INFO(channel, head, head);
+
+	return count;
+}
+
+/**
+ * qcom_smd_send - write data to smd channel
+ * @channel:	channel handle
+ * @data:	buffer of data to write
+ * @len:	number of bytes to write
+ *
+ * This is a blocking write of len bytes into the channel's tx ring buffer and
+ * signal the remote end. It will sleep until there is enough space available
+ * in the tx buffer, utilizing the fBLOCKREADINTR signaling mechanism to avoid
+ * polling.
+ */
+static int __qcom_smd_send(struct qcom_smd_channel *channel, const void *data,
+			   int len, bool wait)
+{
+	__le32 hdr[5] = { cpu_to_le32(len), };
+	int tlen = sizeof(hdr) + len;
+	int ret;
+
+	/* Word aligned channels only accept word size aligned data */
+	if (channel->info_word && len % 4)
+		return -EINVAL;
+
+	/* Reject packets that are too big */
+	if (tlen >= channel->fifo_size)
+		return -EINVAL;
+
+	ret = mutex_lock_interruptible(&channel->tx_lock);
+	if (ret)
+		return ret;
+
+	while (qcom_smd_get_tx_avail(channel) < tlen) {
+		if (!wait) {
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		if (channel->state != SMD_CHANNEL_OPENED) {
+			ret = -EPIPE;
+			goto out;
+		}
+
+		SET_TX_CHANNEL_FLAG(channel, fBLOCKREADINTR, 0);
+
+		ret = wait_event_interruptible(channel->fblockread_event,
+				       qcom_smd_get_tx_avail(channel) >= tlen ||
+				       channel->state != SMD_CHANNEL_OPENED);
+		if (ret)
+			goto out;
+
+		SET_TX_CHANNEL_FLAG(channel, fBLOCKREADINTR, 1);
+	}
+
+	SET_TX_CHANNEL_FLAG(channel, fTAIL, 0);
+
+	qcom_smd_write_fifo(channel, hdr, sizeof(hdr));
+	qcom_smd_write_fifo(channel, data, len);
+
+	SET_TX_CHANNEL_FLAG(channel, fHEAD, 1);
+
+	/* Ensure ordering of channel info updates */
+	wmb();
+
+	qcom_smd_signal_channel(channel);
+
+out:
+	mutex_unlock(&channel->tx_lock);
+
+	return ret;
+}
+
+/*
+ * Helper for opening a channel
+ */
+static int qcom_smd_channel_open(struct qcom_smd_channel *channel,
+				 rpmsg_rx_cb_t cb)
+{
+	size_t bb_size;
+
+	/*
+	 * Packets are maximum 4k, but reduce if the fifo is smaller
+	 */
+	bb_size = min(channel->fifo_size, SZ_4K);
+	channel->bounce_buffer = kmalloc(bb_size, GFP_KERNEL);
+	if (!channel->bounce_buffer)
+		return -ENOMEM;
+
+	qcom_smd_channel_set_callback(channel, cb);
+	qcom_smd_channel_set_state(channel, SMD_CHANNEL_OPENING);
+	qcom_smd_channel_set_state(channel, SMD_CHANNEL_OPENED);
+
+	return 0;
+}
+
+/*
+ * Helper for closing and resetting a channel
+ */
+static void qcom_smd_channel_close(struct qcom_smd_channel *channel)
+{
+	qcom_smd_channel_set_callback(channel, NULL);
+
+	kfree(channel->bounce_buffer);
+	channel->bounce_buffer = NULL;
+
+	qcom_smd_channel_set_state(channel, SMD_CHANNEL_CLOSED);
+	qcom_smd_channel_reset(channel);
+}
+
+static struct qcom_smd_channel *
+qcom_smd_find_channel(struct qcom_smd_edge *edge, const char *name)
+{
+	struct qcom_smd_channel *channel;
+	struct qcom_smd_channel *ret = NULL;
+	unsigned long flags;
+	unsigned state;
+
+	spin_lock_irqsave(&edge->channels_lock, flags);
+	list_for_each_entry(channel, &edge->channels, list) {
+		if (strcmp(channel->name, name))
+			continue;
+
+		state = GET_RX_CHANNEL_INFO(channel, state);
+		if (state != SMD_CHANNEL_OPENING &&
+		    state != SMD_CHANNEL_OPENED)
+			continue;
+
+		ret = channel;
+		break;
+	}
+	spin_unlock_irqrestore(&edge->channels_lock, flags);
+
+	return ret;
+}
+
+static void __ept_release(struct kref *kref)
+{
+	struct rpmsg_endpoint *ept = container_of(kref, struct rpmsg_endpoint,
+						  refcount);
+	kfree(to_smd_endpoint(ept));
+}
+
+static struct rpmsg_endpoint *qcom_smd_create_ept(struct rpmsg_device *rpdev,
+						  rpmsg_rx_cb_t cb, void *priv,
+						  struct rpmsg_channel_info chinfo)
+{
+	struct qcom_smd_endpoint *qsept;
+	struct qcom_smd_channel *channel;
+	struct qcom_smd_device *qsdev = to_smd_device(&rpdev->dev);
+	struct qcom_smd_edge *edge = qsdev->edge;
+	struct rpmsg_endpoint *ept;
+	const char *name = chinfo.name;
+	int ret;
+
+	/* Wait up to HZ for the channel to appear */
+	ret = wait_event_interruptible_timeout(edge->new_channel_event,
+			(channel = qcom_smd_find_channel(edge, name)) != NULL,
+			HZ);
+	if (!ret)
+		return NULL;
+
+	if (channel->state != SMD_CHANNEL_CLOSED) {
+		dev_err(&rpdev->dev, "channel %s is busy\n", channel->name);
+		return NULL;
+	}
+
+	qsept = kzalloc(sizeof(*qsept), GFP_KERNEL);
+	if (!qsept)
+		return NULL;
+
+	ept = &qsept->ept;
+
+	kref_init(&ept->refcount);
+
+	ept->rpdev = rpdev;
+	ept->cb = cb;
+	ept->priv = priv;
+
+	channel->qsept = qsept;
+	qsept->qsch = channel;
+
+	ret = qcom_smd_channel_open(channel, cb);
+	if (ret)
+		goto free_ept;
+
+	return ept;
+
+free_ept:
+	channel->qsept = NULL;
+	kref_put(&ept->refcount, __ept_release);
+	return NULL;
+}
+
+static void qcom_smd_destroy_ept(struct rpmsg_endpoint *ept)
+{
+	struct qcom_smd_endpoint *qsept = to_smd_endpoint(ept);
+	struct qcom_smd_channel *ch = qsept->qsch;
+
+	qcom_smd_channel_close(ch);
+	ch->qsept = NULL;
+	kref_put(&ept->refcount, __ept_release);
+}
+
+static int qcom_smd_send(struct rpmsg_endpoint *ept, void *data, int len)
+{
+	struct qcom_smd_endpoint *qsept = to_smd_endpoint(ept);
+
+	return __qcom_smd_send(qsept->qsch, data, len, true);
+}
+
+static int qcom_smd_trysend(struct rpmsg_endpoint *ept, void *data, int len)
+{
+	struct qcom_smd_endpoint *qsept = to_smd_endpoint(ept);
+
+	return __qcom_smd_send(qsept->qsch, data, len, false);
+}
+
+/*
+ * Finds the device_node for the smd child interested in this channel.
+ */
+static struct device_node *qcom_smd_match_channel(struct device_node *edge_node,
+						  const char *channel)
+{
+	struct device_node *child;
+	const char *name;
+	const char *key;
+	int ret;
+
+	for_each_available_child_of_node(edge_node, child) {
+		key = "qcom,smd-channels";
+		ret = of_property_read_string(child, key, &name);
+		if (ret)
+			continue;
+
+		if (strcmp(name, channel) == 0)
+			return child;
+	}
+
+	return NULL;
+}
+
+static const struct rpmsg_channel qcom_smd_rpmsg_ops = {
+	.create_ept = qcom_smd_create_ept,
+	.destroy_ept = qcom_smd_destroy_ept,
+	.send = qcom_smd_send,
+	.trysend = qcom_smd_trysend,
+};
+
+/*
+ * Create a smd client device for channel that is being opened.
+ */
+static int qcom_smd_create_device(struct qcom_smd_channel *channel)
+{
+	struct qcom_smd_device *qsdev;
+	struct rpmsg_device *rpdev;
+	struct qcom_smd_edge *edge = channel->edge;
+
+	dev_dbg(&edge->dev, "registering '%s'\n", channel->name);
+
+	qsdev = kzalloc(sizeof(*qsdev), GFP_KERNEL);
+	if (!qsdev)
+		return -ENOMEM;
+
+	/* Link qsdev to our SMD edge */
+	qsdev->edge = edge;
+
+	/* Assign callbacks for rpmsg_channel */
+	qsdev->rpch = qcom_smd_rpmsg_ops;
+
+	/* Assign public information to the rpmsg_device */
+	rpdev = &qsdev->rpch.rpdev;
+	strncpy(rpdev->id.name, channel->name, RPMSG_NAME_SIZE);
+	rpdev->src = RPMSG_ADDR_ANY;
+	rpdev->dst = RPMSG_ADDR_ANY;
+
+	rpdev->dev.of_node = qcom_smd_match_channel(edge->of_node, channel->name);
+	rpdev->dev.parent = &edge->dev;
+
+	return rpmsg_register_device(rpdev);
+}
+
+/*
+ * Allocate the qcom_smd_channel object for a newly found smd channel,
+ * retrieving and validating the smem items involved.
+ */
+static struct qcom_smd_channel *qcom_smd_create_channel(struct qcom_smd_edge *edge,
+							unsigned smem_info_item,
+							unsigned smem_fifo_item,
+							char *name)
+{
+	struct qcom_smd_channel *channel;
+	size_t fifo_size;
+	size_t info_size;
+	void *fifo_base;
+	void *info;
+	int ret;
+
+	channel = devm_kzalloc(&edge->dev, sizeof(*channel), GFP_KERNEL);
+	if (!channel)
+		return ERR_PTR(-ENOMEM);
+
+	channel->edge = edge;
+	channel->name = devm_kstrdup(&edge->dev, name, GFP_KERNEL);
+	if (!channel->name)
+		return ERR_PTR(-ENOMEM);
+
+	mutex_init(&channel->tx_lock);
+	spin_lock_init(&channel->recv_lock);
+	init_waitqueue_head(&channel->fblockread_event);
+
+	info = qcom_smem_get(edge->remote_pid, smem_info_item, &info_size);
+	if (IS_ERR(info)) {
+		ret = PTR_ERR(info);
+		goto free_name_and_channel;
+	}
+
+	/*
+	 * Use the size of the item to figure out which channel info struct to
+	 * use.
+	 */
+	if (info_size == 2 * sizeof(struct smd_channel_info_word)) {
+		channel->info_word = info;
+	} else if (info_size == 2 * sizeof(struct smd_channel_info)) {
+		channel->info = info;
+	} else {
+		dev_err(&edge->dev,
+			"channel info of size %zu not supported\n", info_size);
+		ret = -EINVAL;
+		goto free_name_and_channel;
+	}
+
+	fifo_base = qcom_smem_get(edge->remote_pid, smem_fifo_item, &fifo_size);
+	if (IS_ERR(fifo_base)) {
+		ret =  PTR_ERR(fifo_base);
+		goto free_name_and_channel;
+	}
+
+	/* The channel consist of a rx and tx fifo of equal size */
+	fifo_size /= 2;
+
+	dev_dbg(&edge->dev, "new channel '%s' info-size: %zu fifo-size: %zu\n",
+			  name, info_size, fifo_size);
+
+	channel->tx_fifo = fifo_base;
+	channel->rx_fifo = fifo_base + fifo_size;
+	channel->fifo_size = fifo_size;
+
+	qcom_smd_channel_reset(channel);
+
+	return channel;
+
+free_name_and_channel:
+	devm_kfree(&edge->dev, channel->name);
+	devm_kfree(&edge->dev, channel);
+
+	return ERR_PTR(ret);
+}
+
+/*
+ * Scans the allocation table for any newly allocated channels, calls
+ * qcom_smd_create_channel() to create representations of these and add
+ * them to the edge's list of channels.
+ */
+static void qcom_channel_scan_worker(struct work_struct *work)
+{
+	struct qcom_smd_edge *edge = container_of(work, struct qcom_smd_edge, scan_work);
+	struct qcom_smd_alloc_entry *alloc_tbl;
+	struct qcom_smd_alloc_entry *entry;
+	struct qcom_smd_channel *channel;
+	unsigned long flags;
+	unsigned fifo_id;
+	unsigned info_id;
+	int tbl;
+	int i;
+	u32 eflags, cid;
+
+	for (tbl = 0; tbl < SMD_ALLOC_TBL_COUNT; tbl++) {
+		alloc_tbl = qcom_smem_get(edge->remote_pid,
+				    smem_items[tbl].alloc_tbl_id, NULL);
+		if (IS_ERR(alloc_tbl))
+			continue;
+
+		for (i = 0; i < SMD_ALLOC_TBL_SIZE; i++) {
+			entry = &alloc_tbl[i];
+			eflags = le32_to_cpu(entry->flags);
+			if (test_bit(i, edge->allocated[tbl]))
+				continue;
+
+			if (entry->ref_count == 0)
+				continue;
+
+			if (!entry->name[0])
+				continue;
+
+			if (!(eflags & SMD_CHANNEL_FLAGS_PACKET))
+				continue;
+
+			if ((eflags & SMD_CHANNEL_FLAGS_EDGE_MASK) != edge->edge_id)
+				continue;
+
+			cid = le32_to_cpu(entry->cid);
+			info_id = smem_items[tbl].info_base_id + cid;
+			fifo_id = smem_items[tbl].fifo_base_id + cid;
+
+			channel = qcom_smd_create_channel(edge, info_id, fifo_id, entry->name);
+			if (IS_ERR(channel))
+				continue;
+
+			spin_lock_irqsave(&edge->channels_lock, flags);
+			list_add(&channel->list, &edge->channels);
+			spin_unlock_irqrestore(&edge->channels_lock, flags);
+
+			dev_dbg(&edge->dev, "new channel found: '%s'\n", channel->name);
+			set_bit(i, edge->allocated[tbl]);
+
+			wake_up_interruptible(&edge->new_channel_event);
+		}
+	}
+
+	schedule_work(&edge->state_work);
+}
+
+/*
+ * This per edge worker scans smem for any new channels and register these. It
+ * then scans all registered channels for state changes that should be handled
+ * by creating or destroying smd client devices for the registered channels.
+ *
+ * LOCKING: edge->channels_lock only needs to cover the list operations, as the
+ * worker is killed before any channels are deallocated
+ */
+static void qcom_channel_state_worker(struct work_struct *work)
+{
+	struct qcom_smd_channel *channel;
+	struct qcom_smd_edge *edge = container_of(work,
+						  struct qcom_smd_edge,
+						  state_work);
+	struct rpmsg_channel_info chinfo;
+	unsigned remote_state;
+	unsigned long flags;
+
+	/*
+	 * Register a device for any closed channel where the remote processor
+	 * is showing interest in opening the channel.
+	 */
+	spin_lock_irqsave(&edge->channels_lock, flags);
+	list_for_each_entry(channel, &edge->channels, list) {
+		if (channel->state != SMD_CHANNEL_CLOSED)
+			continue;
+
+		remote_state = GET_RX_CHANNEL_INFO(channel, state);
+		if (remote_state != SMD_CHANNEL_OPENING &&
+		    remote_state != SMD_CHANNEL_OPENED)
+			continue;
+
+		if (channel->registered)
+			continue;
+
+		spin_unlock_irqrestore(&edge->channels_lock, flags);
+		qcom_smd_create_device(channel);
+		channel->registered = true;
+		spin_lock_irqsave(&edge->channels_lock, flags);
+
+		channel->registered = true;
+	}
+
+	/*
+	 * Unregister the device for any channel that is opened where the
+	 * remote processor is closing the channel.
+	 */
+	list_for_each_entry(channel, &edge->channels, list) {
+		if (channel->state != SMD_CHANNEL_OPENING &&
+		    channel->state != SMD_CHANNEL_OPENED)
+			continue;
+
+		remote_state = GET_RX_CHANNEL_INFO(channel, state);
+		if (remote_state == SMD_CHANNEL_OPENING ||
+		    remote_state == SMD_CHANNEL_OPENED)
+			continue;
+
+		spin_unlock_irqrestore(&edge->channels_lock, flags);
+
+		strncpy(chinfo.name, channel->name, sizeof(chinfo.name));
+		chinfo.src = RPMSG_ADDR_ANY;
+		chinfo.dst = RPMSG_ADDR_ANY;
+		rpmsg_unregister_device(&edge->dev, &chinfo);
+		channel->registered = false;
+		spin_lock_irqsave(&edge->channels_lock, flags);
+	}
+	spin_unlock_irqrestore(&edge->channels_lock, flags);
+}
+
+/*
+ * Parses an of_node describing an edge.
+ */
+static int qcom_smd_parse_edge(struct device *dev,
+			       struct device_node *node,
+			       struct qcom_smd_edge *edge)
+{
+	struct device_node *syscon_np;
+	const char *key;
+	int irq;
+	int ret;
+
+	INIT_LIST_HEAD(&edge->channels);
+	spin_lock_init(&edge->channels_lock);
+
+	INIT_WORK(&edge->scan_work, qcom_channel_scan_worker);
+	INIT_WORK(&edge->state_work, qcom_channel_state_worker);
+
+	edge->of_node = of_node_get(node);
+
+	key = "qcom,smd-edge";
+	ret = of_property_read_u32(node, key, &edge->edge_id);
+	if (ret) {
+		dev_err(dev, "edge missing %s property\n", key);
+		return -EINVAL;
+	}
+
+	edge->remote_pid = QCOM_SMEM_HOST_ANY;
+	key = "qcom,remote-pid";
+	of_property_read_u32(node, key, &edge->remote_pid);
+
+	syscon_np = of_parse_phandle(node, "qcom,ipc", 0);
+	if (!syscon_np) {
+		dev_err(dev, "no qcom,ipc node\n");
+		return -ENODEV;
+	}
+
+	edge->ipc_regmap = syscon_node_to_regmap(syscon_np);
+	if (IS_ERR(edge->ipc_regmap))
+		return PTR_ERR(edge->ipc_regmap);
+
+	key = "qcom,ipc";
+	ret = of_property_read_u32_index(node, key, 1, &edge->ipc_offset);
+	if (ret < 0) {
+		dev_err(dev, "no offset in %s\n", key);
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32_index(node, key, 2, &edge->ipc_bit);
+	if (ret < 0) {
+		dev_err(dev, "no bit in %s\n", key);
+		return -EINVAL;
+	}
+
+	irq = irq_of_parse_and_map(node, 0);
+	if (irq < 0) {
+		dev_err(dev, "required smd interrupt missing\n");
+		return -EINVAL;
+	}
+
+	ret = devm_request_irq(dev, irq,
+			       qcom_smd_edge_intr, IRQF_TRIGGER_RISING,
+			       node->name, edge);
+	if (ret) {
+		dev_err(dev, "failed to request smd irq\n");
+		return ret;
+	}
+
+	edge->irq = irq;
+
+	return 0;
+}
+
+/*
+ * Release function for an edge.
+  * Reset the state of each associated channel and free the edge context.
+ */
+static void qcom_smd_edge_release(struct device *dev)
+{
+	struct qcom_smd_channel *channel;
+	struct qcom_smd_edge *edge = to_smd_edge(dev);
+
+	list_for_each_entry(channel, &edge->channels, list) {
+		SET_RX_CHANNEL_INFO(channel, state, SMD_CHANNEL_CLOSED);
+		SET_RX_CHANNEL_INFO(channel, head, 0);
+		SET_RX_CHANNEL_INFO(channel, tail, 0);
+	}
+
+	kfree(edge);
+}
+
+/**
+ * qcom_smd_register_edge() - register an edge based on an device_node
+ * @parent:    parent device for the edge
+ * @node:      device_node describing the edge
+ *
+ * Returns an edge reference, or negative ERR_PTR() on failure.
+ */
+struct qcom_smd_edge *qcom_smd_register_edge(struct device *parent,
+					     struct device_node *node)
+{
+	struct qcom_smd_edge *edge;
+	int ret;
+
+	edge = kzalloc(sizeof(*edge), GFP_KERNEL);
+	if (!edge)
+		return ERR_PTR(-ENOMEM);
+
+	init_waitqueue_head(&edge->new_channel_event);
+
+	edge->dev.parent = parent;
+	edge->dev.release = qcom_smd_edge_release;
+	dev_set_name(&edge->dev, "%s:%s", dev_name(parent), node->name);
+	ret = device_register(&edge->dev);
+	if (ret) {
+		pr_err("failed to register smd edge\n");
+		return ERR_PTR(ret);
+	}
+
+	ret = qcom_smd_parse_edge(&edge->dev, node, edge);
+	if (ret) {
+		dev_err(&edge->dev, "failed to parse smd edge\n");
+		goto unregister_dev;
+	}
+
+	schedule_work(&edge->scan_work);
+
+	return edge;
+
+unregister_dev:
+	put_device(&edge->dev);
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL(qcom_smd_register_edge);
+
+static int qcom_smd_remove_device(struct device *dev, void *data)
+{
+	device_unregister(dev);
+
+	return 0;
+}
+
+/**
+ * qcom_smd_unregister_edge() - release an edge and its children
+ * @edge:      edge reference acquired from qcom_smd_register_edge
+ */
+int qcom_smd_unregister_edge(struct qcom_smd_edge *edge)
+{
+	int ret;
+
+	disable_irq(edge->irq);
+	cancel_work_sync(&edge->scan_work);
+	cancel_work_sync(&edge->state_work);
+
+	ret = device_for_each_child(&edge->dev, NULL, qcom_smd_remove_device);
+	if (ret)
+		dev_warn(&edge->dev, "can't remove smd device: %d\n", ret);
+
+	device_unregister(&edge->dev);
+
+	return 0;
+}
+EXPORT_SYMBOL(qcom_smd_unregister_edge);
+
+static int qcom_smd_probe(struct platform_device *pdev)
+{
+	struct device_node *node;
+	void *p;
+
+	/* Wait for smem */
+	p = qcom_smem_get(QCOM_SMEM_HOST_ANY, smem_items[0].alloc_tbl_id, NULL);
+	if (PTR_ERR(p) == -EPROBE_DEFER)
+		return PTR_ERR(p);
+
+	for_each_available_child_of_node(pdev->dev.of_node, node)
+		qcom_smd_register_edge(&pdev->dev, node);
+
+	return 0;
+}
+
+static int qcom_smd_remove_edge(struct device *dev, void *data)
+{
+	struct qcom_smd_edge *edge = to_smd_edge(dev);
+
+	return qcom_smd_unregister_edge(edge);
+}
+
+/*
+ * Shut down all smd clients by making sure that each edge stops processing
+ * events and scanning for new channels, then call destroy on the devices.
+ */
+static int qcom_smd_remove(struct platform_device *pdev)
+{
+	int ret;
+
+	ret = device_for_each_child(&pdev->dev, NULL, qcom_smd_remove_edge);
+	if (ret)
+		dev_warn(&pdev->dev, "can't remove smd device: %d\n", ret);
+
+	return ret;
+}
+
+static const struct of_device_id qcom_smd_of_match[] = {
+	{ .compatible = "qcom,smd" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, qcom_smd_of_match);
+
+static struct platform_driver qcom_smd_driver = {
+	.probe = qcom_smd_probe,
+	.remove = qcom_smd_remove,
+	.driver = {
+		.name = "qcom-smd",
+		.of_match_table = qcom_smd_of_match,
+	},
+};
+
+static int __init qcom_smd_init(void)
+{
+	return platform_driver_register(&qcom_smd_driver);
+}
+subsys_initcall(qcom_smd_init);
+
+static void __exit qcom_smd_exit(void)
+{
+	platform_driver_unregister(&qcom_smd_driver);
+}
+module_exit(qcom_smd_exit);
+
+MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@sonymobile.com>");
+MODULE_DESCRIPTION("Qualcomm Shared Memory Driver");
+MODULE_LICENSE("GPL v2");
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH 14/14] rpmsg: Introduce Qualcomm SMD backend
@ 2016-08-16  0:17   ` Bjorn Andersson
  0 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-16  0:17 UTC (permalink / raw)
  To: linux-arm-kernel

This introduces a new rpmsg backend for the Qualcomm SMD system,
allowing communication with various remote processors found in Qualcomm
platforms. The implementation is based on, and intends to replace,
drivers/soc/qcom/smd.c with the necessary adaptions for fitting with the
rpmsg core.

Based on original work by Sricharan R <sricharan@codeaurora.org>

Cc: Sricharan R <sricharan@codeaurora.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---

I've been unable to find a feasible way to migrate the existing SMD
implementation, so instead this is based on a copy of the current SMD
implementation. With this in place the drivers can be transitioned in one go
and the old implementation can be dropped.

 drivers/rpmsg/Kconfig    |   10 +
 drivers/rpmsg/Makefile   |    1 +
 drivers/rpmsg/qcom_smd.c | 1448 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 1459 insertions(+)
 create mode 100644 drivers/rpmsg/qcom_smd.c

diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig
index 40614be88c97..bdbec8124d8f 100644
--- a/drivers/rpmsg/Kconfig
+++ b/drivers/rpmsg/Kconfig
@@ -10,4 +10,14 @@ config RPMSG_VIRTIO
 	select VIRTIO
 	select VIRTUALIZATION
 
+config RPMSG_QCOM_SMD
+	tristate "Qualcomm Shared Memory Driver (SMD)"
+	depends on QCOM_SMEM
+	depends on !QCOM_SMD
+	select RPMSG
+	help
+	  Say y here to enable support for the Qualcomm Shared Memory Driver
+	  providing communication channels to remote processors in Qualcomm
+	  platforms.
+
 endmenu
diff --git a/drivers/rpmsg/Makefile b/drivers/rpmsg/Makefile
index 383213417a00..eb5211efedc4 100644
--- a/drivers/rpmsg/Makefile
+++ b/drivers/rpmsg/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_RPMSG)	+= rpmsg_core.o
 obj-$(CONFIG_RPMSG_VIRTIO) += virtio_rpmsg_bus.o
+obj-$(CONFIG_RPMSG_QCOM_SMD) += qcom_smd.o
diff --git a/drivers/rpmsg/qcom_smd.c b/drivers/rpmsg/qcom_smd.c
new file mode 100644
index 000000000000..eff87ac954e7
--- /dev/null
+++ b/drivers/rpmsg/qcom_smd.c
@@ -0,0 +1,1448 @@
+/*
+ * Copyright (c) 2015, Sony Mobile Communications AB.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/soc/qcom/smem.h>
+#include <linux/wait.h>
+#include <linux/rpmsg.h>
+
+#include "rpmsg_internal.h"
+
+/*
+ * The Qualcomm Shared Memory communication solution provides point-to-point
+ * channels for clients to send and receive streaming or packet based data.
+ *
+ * Each channel consists of a control item (channel info) and a ring buffer
+ * pair. The channel info carry information related to channel state, flow
+ * control and the offsets within the ring buffer.
+ *
+ * All allocated channels are listed in an allocation table, identifying the
+ * pair of items by name, type and remote processor.
+ *
+ * Upon creating a new channel the remote processor allocates channel info and
+ * ring buffer items from the smem heap and populate the allocation table. An
+ * interrupt is sent to the other end of the channel and a scan for new
+ * channels should be done. A channel never goes away, it will only change
+ * state.
+ *
+ * The remote processor signals it intent for bring up the communication
+ * channel by setting the state of its end of the channel to "opening" and
+ * sends out an interrupt. We detect this change and register a smd device to
+ * consume the channel. Upon finding a consumer we finish the handshake and the
+ * channel is up.
+ *
+ * Upon closing a channel, the remote processor will update the state of its
+ * end of the channel and signal us, we will then unregister any attached
+ * device and close our end of the channel.
+ *
+ * Devices attached to a channel can use the qcom_smd_send function to push
+ * data to the channel, this is done by copying the data into the tx ring
+ * buffer, updating the pointers in the channel info and signaling the remote
+ * processor.
+ *
+ * The remote processor does the equivalent when it transfer data and upon
+ * receiving the interrupt we check the channel info for new data and delivers
+ * this to the attached device. If the device is not ready to receive the data
+ * we leave it in the ring buffer for now.
+ */
+
+struct smd_channel_info;
+struct smd_channel_info_pair;
+struct smd_channel_info_word;
+struct smd_channel_info_word_pair;
+
+#define SMD_ALLOC_TBL_COUNT	2
+#define SMD_ALLOC_TBL_SIZE	64
+
+/*
+ * This lists the various smem heap items relevant for the allocation table and
+ * smd channel entries.
+ */
+static const struct {
+	unsigned alloc_tbl_id;
+	unsigned info_base_id;
+	unsigned fifo_base_id;
+} smem_items[SMD_ALLOC_TBL_COUNT] = {
+	{
+		.alloc_tbl_id = 13,
+		.info_base_id = 14,
+		.fifo_base_id = 338
+	},
+	{
+		.alloc_tbl_id = 266,
+		.info_base_id = 138,
+		.fifo_base_id = 202,
+	},
+};
+
+/**
+ * struct qcom_smd_edge - representing a remote processor
+ * @of_node:		of_node handle for information related to this edge
+ * @edge_id:		identifier of this edge
+ * @remote_pid:		identifier of remote processor
+ * @irq:		interrupt for signals on this edge
+ * @ipc_regmap:		regmap handle holding the outgoing ipc register
+ * @ipc_offset:		offset within @ipc_regmap of the register for ipc
+ * @ipc_bit:		bit in the register at @ipc_offset of @ipc_regmap
+ * @channels:		list of all channels detected on this edge
+ * @channels_lock:	guard for modifications of @channels
+ * @allocated:		array of bitmaps representing already allocated channels
+ * @smem_available:	last available amount of smem triggering a channel scan
+ * @scan_work:		work item for discovering new channels
+ * @state_work:		work item for edge state changes
+ */
+struct qcom_smd_edge {
+	struct device dev;
+
+	struct device_node *of_node;
+	unsigned edge_id;
+	unsigned remote_pid;
+
+	int irq;
+
+	struct regmap *ipc_regmap;
+	int ipc_offset;
+	int ipc_bit;
+
+	struct list_head channels;
+	spinlock_t channels_lock;
+
+	DECLARE_BITMAP(allocated[SMD_ALLOC_TBL_COUNT], SMD_ALLOC_TBL_SIZE);
+
+	unsigned smem_available;
+
+	wait_queue_head_t new_channel_event;
+
+	struct work_struct scan_work;
+	struct work_struct state_work;
+};
+
+/*
+ * SMD channel states.
+ */
+enum smd_channel_state {
+	SMD_CHANNEL_CLOSED,
+	SMD_CHANNEL_OPENING,
+	SMD_CHANNEL_OPENED,
+	SMD_CHANNEL_FLUSHING,
+	SMD_CHANNEL_CLOSING,
+	SMD_CHANNEL_RESET,
+	SMD_CHANNEL_RESET_OPENING
+};
+
+struct qcom_smd_device {
+	struct rpmsg_channel rpch;
+
+	struct qcom_smd_edge *edge;
+};
+
+static inline struct qcom_smd_device *to_smd_device(struct device *d)
+{
+	struct rpmsg_channel *rpch = to_rpmsg_channel(d);
+
+	return container_of(rpch, struct qcom_smd_device, rpch);
+}
+
+struct qcom_smd_endpoint {
+	struct rpmsg_endpoint ept;
+
+	struct qcom_smd_channel *qsch;
+};
+
+#define to_smd_edge(d) container_of(d, struct qcom_smd_edge, dev)
+#define to_smd_endpoint(ept) container_of(ept, struct qcom_smd_endpoint, ept)
+
+/**
+ * struct qcom_smd_channel - smd channel struct
+ * @edge:		qcom_smd_edge this channel is living on
+ * @qsdev:		reference to a associated smd client device
+ * @name:		name of the channel
+ * @state:		local state of the channel
+ * @remote_state:	remote state of the channel
+ * @info:		byte aligned outgoing/incoming channel info
+ * @info_word:		word aligned outgoing/incoming channel info
+ * @tx_lock:		lock to make writes to the channel mutually exclusive
+ * @fblockread_event:	wakeup event tied to tx fBLOCKREADINTR
+ * @tx_fifo:		pointer to the outgoing ring buffer
+ * @rx_fifo:		pointer to the incoming ring buffer
+ * @fifo_size:		size of each ring buffer
+ * @bounce_buffer:	bounce buffer for reading wrapped packets
+ * @cb:			callback function registered for this channel
+ * @recv_lock:		guard for rx info modifications and cb pointer
+ * @pkt_size:		size of the currently handled packet
+ * @list:		lite entry for @channels in qcom_smd_edge
+ */
+struct qcom_smd_channel {
+	struct qcom_smd_edge *edge;
+
+	struct qcom_smd_endpoint *qsept;
+	bool registered;
+
+	char *name;
+	enum smd_channel_state state;
+	enum smd_channel_state remote_state;
+
+	struct smd_channel_info_pair *info;
+	struct smd_channel_info_word_pair *info_word;
+
+	struct mutex tx_lock;
+	wait_queue_head_t fblockread_event;
+
+	void *tx_fifo;
+	void *rx_fifo;
+	int fifo_size;
+
+	void *bounce_buffer;
+
+	spinlock_t recv_lock;
+
+	int pkt_size;
+
+	void *drvdata;
+
+	struct list_head list;
+};
+
+/*
+ * Format of the smd_info smem items, for byte aligned channels.
+ */
+struct smd_channel_info {
+	__le32 state;
+	u8  fDSR;
+	u8  fCTS;
+	u8  fCD;
+	u8  fRI;
+	u8  fHEAD;
+	u8  fTAIL;
+	u8  fSTATE;
+	u8  fBLOCKREADINTR;
+	__le32 tail;
+	__le32 head;
+};
+
+struct smd_channel_info_pair {
+	struct smd_channel_info tx;
+	struct smd_channel_info rx;
+};
+
+/*
+ * Format of the smd_info smem items, for word aligned channels.
+ */
+struct smd_channel_info_word {
+	__le32 state;
+	__le32 fDSR;
+	__le32 fCTS;
+	__le32 fCD;
+	__le32 fRI;
+	__le32 fHEAD;
+	__le32 fTAIL;
+	__le32 fSTATE;
+	__le32 fBLOCKREADINTR;
+	__le32 tail;
+	__le32 head;
+};
+
+struct smd_channel_info_word_pair {
+	struct smd_channel_info_word tx;
+	struct smd_channel_info_word rx;
+};
+
+#define GET_RX_CHANNEL_FLAG(channel, param)				     \
+	({								     \
+		BUILD_BUG_ON(sizeof(channel->info->rx.param) != sizeof(u8)); \
+		channel->info_word ?					     \
+			le32_to_cpu(channel->info_word->rx.param) :	     \
+			channel->info->rx.param;			     \
+	})
+
+#define GET_RX_CHANNEL_INFO(channel, param)				      \
+	({								      \
+		BUILD_BUG_ON(sizeof(channel->info->rx.param) != sizeof(u32)); \
+		le32_to_cpu(channel->info_word ?			      \
+			channel->info_word->rx.param :			      \
+			channel->info->rx.param);			      \
+	})
+
+#define SET_RX_CHANNEL_FLAG(channel, param, value)			     \
+	({								     \
+		BUILD_BUG_ON(sizeof(channel->info->rx.param) != sizeof(u8)); \
+		if (channel->info_word)					     \
+			channel->info_word->rx.param = cpu_to_le32(value);   \
+		else							     \
+			channel->info->rx.param = value;		     \
+	})
+
+#define SET_RX_CHANNEL_INFO(channel, param, value)			      \
+	({								      \
+		BUILD_BUG_ON(sizeof(channel->info->rx.param) != sizeof(u32)); \
+		if (channel->info_word)					      \
+			channel->info_word->rx.param = cpu_to_le32(value);    \
+		else							      \
+			channel->info->rx.param = cpu_to_le32(value);	      \
+	})
+
+#define GET_TX_CHANNEL_FLAG(channel, param)				     \
+	({								     \
+		BUILD_BUG_ON(sizeof(channel->info->tx.param) != sizeof(u8)); \
+		channel->info_word ?					     \
+			le32_to_cpu(channel->info_word->tx.param) :          \
+			channel->info->tx.param;			     \
+	})
+
+#define GET_TX_CHANNEL_INFO(channel, param)				      \
+	({								      \
+		BUILD_BUG_ON(sizeof(channel->info->tx.param) != sizeof(u32)); \
+		le32_to_cpu(channel->info_word ?			      \
+			channel->info_word->tx.param :			      \
+			channel->info->tx.param);			      \
+	})
+
+#define SET_TX_CHANNEL_FLAG(channel, param, value)			     \
+	({								     \
+		BUILD_BUG_ON(sizeof(channel->info->tx.param) != sizeof(u8)); \
+		if (channel->info_word)					     \
+			channel->info_word->tx.param = cpu_to_le32(value);   \
+		else							     \
+			channel->info->tx.param = value;		     \
+	})
+
+#define SET_TX_CHANNEL_INFO(channel, param, value)			      \
+	({								      \
+		BUILD_BUG_ON(sizeof(channel->info->tx.param) != sizeof(u32)); \
+		if (channel->info_word)					      \
+			channel->info_word->tx.param = cpu_to_le32(value);   \
+		else							      \
+			channel->info->tx.param = cpu_to_le32(value);	      \
+	})
+
+/**
+ * struct qcom_smd_alloc_entry - channel allocation entry
+ * @name:	channel name
+ * @cid:	channel index
+ * @flags:	channel flags and edge id
+ * @ref_count:	reference count of the channel
+ */
+struct qcom_smd_alloc_entry {
+	u8 name[20];
+	__le32 cid;
+	__le32 flags;
+	__le32 ref_count;
+} __packed;
+
+#define SMD_CHANNEL_FLAGS_EDGE_MASK	0xff
+#define SMD_CHANNEL_FLAGS_STREAM	BIT(8)
+#define SMD_CHANNEL_FLAGS_PACKET	BIT(9)
+
+/*
+ * Each smd packet contains a 20 byte header, with the first 4 being the length
+ * of the packet.
+ */
+#define SMD_PACKET_HEADER_LEN	20
+
+/*
+ * Signal the remote processor associated with 'channel'.
+ */
+static void qcom_smd_signal_channel(struct qcom_smd_channel *channel)
+{
+	struct qcom_smd_edge *edge = channel->edge;
+
+	regmap_write(edge->ipc_regmap, edge->ipc_offset, BIT(edge->ipc_bit));
+}
+
+/*
+ * Initialize the tx channel info
+ */
+static void qcom_smd_channel_reset(struct qcom_smd_channel *channel)
+{
+	SET_TX_CHANNEL_INFO(channel, state, SMD_CHANNEL_CLOSED);
+	SET_TX_CHANNEL_FLAG(channel, fDSR, 0);
+	SET_TX_CHANNEL_FLAG(channel, fCTS, 0);
+	SET_TX_CHANNEL_FLAG(channel, fCD, 0);
+	SET_TX_CHANNEL_FLAG(channel, fRI, 0);
+	SET_TX_CHANNEL_FLAG(channel, fHEAD, 0);
+	SET_TX_CHANNEL_FLAG(channel, fTAIL, 0);
+	SET_TX_CHANNEL_FLAG(channel, fSTATE, 1);
+	SET_TX_CHANNEL_FLAG(channel, fBLOCKREADINTR, 1);
+	SET_TX_CHANNEL_INFO(channel, head, 0);
+	SET_TX_CHANNEL_INFO(channel, tail, 0);
+
+	qcom_smd_signal_channel(channel);
+
+	channel->state = SMD_CHANNEL_CLOSED;
+	channel->pkt_size = 0;
+}
+
+/*
+ * Set the callback for a channel, with appropriate locking
+ */
+static void qcom_smd_channel_set_callback(struct qcom_smd_channel *channel,
+					  rpmsg_rx_cb_t cb)
+{
+	struct rpmsg_endpoint *ept = &channel->qsept->ept;
+	unsigned long flags;
+
+	spin_lock_irqsave(&channel->recv_lock, flags);
+	ept->cb = cb;
+	spin_unlock_irqrestore(&channel->recv_lock, flags);
+};
+
+/*
+ * Calculate the amount of data available in the rx fifo
+ */
+static size_t qcom_smd_channel_get_rx_avail(struct qcom_smd_channel *channel)
+{
+	unsigned head;
+	unsigned tail;
+
+	head = GET_RX_CHANNEL_INFO(channel, head);
+	tail = GET_RX_CHANNEL_INFO(channel, tail);
+
+	return (head - tail) & (channel->fifo_size - 1);
+}
+
+/*
+ * Set tx channel state and inform the remote processor
+ */
+static void qcom_smd_channel_set_state(struct qcom_smd_channel *channel,
+				       int state)
+{
+	struct qcom_smd_edge *edge = channel->edge;
+	bool is_open = state == SMD_CHANNEL_OPENED;
+
+	if (channel->state == state)
+		return;
+
+	dev_dbg(&edge->dev, "set_state(%s, %d)\n", channel->name, state);
+
+	SET_TX_CHANNEL_FLAG(channel, fDSR, is_open);
+	SET_TX_CHANNEL_FLAG(channel, fCTS, is_open);
+	SET_TX_CHANNEL_FLAG(channel, fCD, is_open);
+
+	SET_TX_CHANNEL_INFO(channel, state, state);
+	SET_TX_CHANNEL_FLAG(channel, fSTATE, 1);
+
+	channel->state = state;
+	qcom_smd_signal_channel(channel);
+}
+
+/*
+ * Copy count bytes of data using 32bit accesses, if that's required.
+ */
+static void smd_copy_to_fifo(void __iomem *dst,
+			     const void *src,
+			     size_t count,
+			     bool word_aligned)
+{
+	if (word_aligned) {
+		__iowrite32_copy(dst, src, count / sizeof(u32));
+	} else {
+		memcpy_toio(dst, src, count);
+	}
+}
+
+/*
+ * Copy count bytes of data using 32bit accesses, if that is required.
+ */
+static void smd_copy_from_fifo(void *dst,
+			       const void __iomem *src,
+			       size_t count,
+			       bool word_aligned)
+{
+	if (word_aligned) {
+		__ioread32_copy(dst, src, count / sizeof(u32));
+	} else {
+		memcpy_fromio(dst, src, count);
+	}
+}
+
+/*
+ * Read count bytes of data from the rx fifo into buf, but don't advance the
+ * tail.
+ */
+static size_t qcom_smd_channel_peek(struct qcom_smd_channel *channel,
+				    void *buf, size_t count)
+{
+	bool word_aligned;
+	unsigned tail;
+	size_t len;
+
+	word_aligned = channel->info_word;
+	tail = GET_RX_CHANNEL_INFO(channel, tail);
+
+	len = min_t(size_t, count, channel->fifo_size - tail);
+	if (len) {
+		smd_copy_from_fifo(buf,
+				   channel->rx_fifo + tail,
+				   len,
+				   word_aligned);
+	}
+
+	if (len != count) {
+		smd_copy_from_fifo(buf + len,
+				   channel->rx_fifo,
+				   count - len,
+				   word_aligned);
+	}
+
+	return count;
+}
+
+/*
+ * Advance the rx tail by count bytes.
+ */
+static void qcom_smd_channel_advance(struct qcom_smd_channel *channel,
+				     size_t count)
+{
+	unsigned tail;
+
+	tail = GET_RX_CHANNEL_INFO(channel, tail);
+	tail += count;
+	tail &= (channel->fifo_size - 1);
+	SET_RX_CHANNEL_INFO(channel, tail, tail);
+}
+
+/*
+ * Read out a single packet from the rx fifo and deliver it to the device
+ */
+static int qcom_smd_channel_recv_single(struct qcom_smd_channel *channel)
+{
+	struct rpmsg_endpoint *ept = &channel->qsept->ept;
+	unsigned tail;
+	size_t len;
+	void *ptr;
+	int ret;
+
+	tail = GET_RX_CHANNEL_INFO(channel, tail);
+
+	/* Use bounce buffer if the data wraps */
+	if (tail + channel->pkt_size >= channel->fifo_size) {
+		ptr = channel->bounce_buffer;
+		len = qcom_smd_channel_peek(channel, ptr, channel->pkt_size);
+	} else {
+		ptr = channel->rx_fifo + tail;
+		len = channel->pkt_size;
+	}
+
+	ret = ept->cb(ept->rpdev, ptr, len, ept->priv, RPMSG_ADDR_ANY);
+	if (ret < 0)
+		return ret;
+
+	/* Only forward the tail if the client consumed the data */
+	qcom_smd_channel_advance(channel, len);
+
+	channel->pkt_size = 0;
+
+	return 0;
+}
+
+/*
+ * Per channel interrupt handling
+ */
+static bool qcom_smd_channel_intr(struct qcom_smd_channel *channel)
+{
+	bool need_state_scan = false;
+	int remote_state;
+	__le32 pktlen;
+	int avail;
+	int ret;
+
+	/* Handle state changes */
+	remote_state = GET_RX_CHANNEL_INFO(channel, state);
+	if (remote_state != channel->remote_state) {
+		channel->remote_state = remote_state;
+		need_state_scan = true;
+	}
+	/* Indicate that we have seen any state change */
+	SET_RX_CHANNEL_FLAG(channel, fSTATE, 0);
+
+	/* Signal waiting qcom_smd_send() about the interrupt */
+	if (!GET_TX_CHANNEL_FLAG(channel, fBLOCKREADINTR))
+		wake_up_interruptible(&channel->fblockread_event);
+
+	/* Don't consume any data until we've opened the channel */
+	if (channel->state != SMD_CHANNEL_OPENED)
+		goto out;
+
+	/* Indicate that we've seen the new data */
+	SET_RX_CHANNEL_FLAG(channel, fHEAD, 0);
+
+	/* Consume data */
+	for (;;) {
+		avail = qcom_smd_channel_get_rx_avail(channel);
+
+		if (!channel->pkt_size && avail >= SMD_PACKET_HEADER_LEN) {
+			qcom_smd_channel_peek(channel, &pktlen, sizeof(pktlen));
+			qcom_smd_channel_advance(channel, SMD_PACKET_HEADER_LEN);
+			channel->pkt_size = le32_to_cpu(pktlen);
+		} else if (channel->pkt_size && avail >= channel->pkt_size) {
+			ret = qcom_smd_channel_recv_single(channel);
+			if (ret)
+				break;
+		} else {
+			break;
+		}
+	}
+
+	/* Indicate that we have seen and updated tail */
+	SET_RX_CHANNEL_FLAG(channel, fTAIL, 1);
+
+	/* Signal the remote that we've consumed the data (if requested) */
+	if (!GET_RX_CHANNEL_FLAG(channel, fBLOCKREADINTR)) {
+		/* Ensure ordering of channel info updates */
+		wmb();
+
+		qcom_smd_signal_channel(channel);
+	}
+
+out:
+	return need_state_scan;
+}
+
+/*
+ * The edge interrupts are triggered by the remote processor on state changes,
+ * channel info updates or when new channels are created.
+ */
+static irqreturn_t qcom_smd_edge_intr(int irq, void *data)
+{
+	struct qcom_smd_edge *edge = data;
+	struct qcom_smd_channel *channel;
+	unsigned available;
+	bool kick_scanner = false;
+	bool kick_state = false;
+
+	/*
+	 * Handle state changes or data on each of the channels on this edge
+	 */
+	spin_lock(&edge->channels_lock);
+	list_for_each_entry(channel, &edge->channels, list) {
+		spin_lock(&channel->recv_lock);
+		kick_state |= qcom_smd_channel_intr(channel);
+		spin_unlock(&channel->recv_lock);
+	}
+	spin_unlock(&edge->channels_lock);
+
+	/*
+	 * Creating a new channel requires allocating an smem entry, so we only
+	 * have to scan if the amount of available space in smem have changed
+	 * since last scan.
+	 */
+	available = qcom_smem_get_free_space(edge->remote_pid);
+	if (available != edge->smem_available) {
+		edge->smem_available = available;
+		kick_scanner = true;
+	}
+
+	if (kick_scanner)
+		schedule_work(&edge->scan_work);
+	if (kick_state)
+		schedule_work(&edge->state_work);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * Delivers any outstanding packets in the rx fifo, can be used after probe of
+ * the clients to deliver any packets that wasn't delivered before the client
+ * was setup.
+ */
+static void qcom_smd_channel_resume(struct qcom_smd_channel *channel)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&channel->recv_lock, flags);
+	qcom_smd_channel_intr(channel);
+	spin_unlock_irqrestore(&channel->recv_lock, flags);
+}
+
+/*
+ * Calculate how much space is available in the tx fifo.
+ */
+static size_t qcom_smd_get_tx_avail(struct qcom_smd_channel *channel)
+{
+	unsigned head;
+	unsigned tail;
+	unsigned mask = channel->fifo_size - 1;
+
+	head = GET_TX_CHANNEL_INFO(channel, head);
+	tail = GET_TX_CHANNEL_INFO(channel, tail);
+
+	return mask - ((head - tail) & mask);
+}
+
+/*
+ * Write count bytes of data into channel, possibly wrapping in the ring buffer
+ */
+static int qcom_smd_write_fifo(struct qcom_smd_channel *channel,
+			       const void *data,
+			       size_t count)
+{
+	bool word_aligned;
+	unsigned head;
+	size_t len;
+
+	word_aligned = channel->info_word;
+	head = GET_TX_CHANNEL_INFO(channel, head);
+
+	len = min_t(size_t, count, channel->fifo_size - head);
+	if (len) {
+		smd_copy_to_fifo(channel->tx_fifo + head,
+				 data,
+				 len,
+				 word_aligned);
+	}
+
+	if (len != count) {
+		smd_copy_to_fifo(channel->tx_fifo,
+				 data + len,
+				 count - len,
+				 word_aligned);
+	}
+
+	head += count;
+	head &= (channel->fifo_size - 1);
+	SET_TX_CHANNEL_INFO(channel, head, head);
+
+	return count;
+}
+
+/**
+ * qcom_smd_send - write data to smd channel
+ * @channel:	channel handle
+ * @data:	buffer of data to write
+ * @len:	number of bytes to write
+ *
+ * This is a blocking write of len bytes into the channel's tx ring buffer and
+ * signal the remote end. It will sleep until there is enough space available
+ * in the tx buffer, utilizing the fBLOCKREADINTR signaling mechanism to avoid
+ * polling.
+ */
+static int __qcom_smd_send(struct qcom_smd_channel *channel, const void *data,
+			   int len, bool wait)
+{
+	__le32 hdr[5] = { cpu_to_le32(len), };
+	int tlen = sizeof(hdr) + len;
+	int ret;
+
+	/* Word aligned channels only accept word size aligned data */
+	if (channel->info_word && len % 4)
+		return -EINVAL;
+
+	/* Reject packets that are too big */
+	if (tlen >= channel->fifo_size)
+		return -EINVAL;
+
+	ret = mutex_lock_interruptible(&channel->tx_lock);
+	if (ret)
+		return ret;
+
+	while (qcom_smd_get_tx_avail(channel) < tlen) {
+		if (!wait) {
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		if (channel->state != SMD_CHANNEL_OPENED) {
+			ret = -EPIPE;
+			goto out;
+		}
+
+		SET_TX_CHANNEL_FLAG(channel, fBLOCKREADINTR, 0);
+
+		ret = wait_event_interruptible(channel->fblockread_event,
+				       qcom_smd_get_tx_avail(channel) >= tlen ||
+				       channel->state != SMD_CHANNEL_OPENED);
+		if (ret)
+			goto out;
+
+		SET_TX_CHANNEL_FLAG(channel, fBLOCKREADINTR, 1);
+	}
+
+	SET_TX_CHANNEL_FLAG(channel, fTAIL, 0);
+
+	qcom_smd_write_fifo(channel, hdr, sizeof(hdr));
+	qcom_smd_write_fifo(channel, data, len);
+
+	SET_TX_CHANNEL_FLAG(channel, fHEAD, 1);
+
+	/* Ensure ordering of channel info updates */
+	wmb();
+
+	qcom_smd_signal_channel(channel);
+
+out:
+	mutex_unlock(&channel->tx_lock);
+
+	return ret;
+}
+
+/*
+ * Helper for opening a channel
+ */
+static int qcom_smd_channel_open(struct qcom_smd_channel *channel,
+				 rpmsg_rx_cb_t cb)
+{
+	size_t bb_size;
+
+	/*
+	 * Packets are maximum 4k, but reduce if the fifo is smaller
+	 */
+	bb_size = min(channel->fifo_size, SZ_4K);
+	channel->bounce_buffer = kmalloc(bb_size, GFP_KERNEL);
+	if (!channel->bounce_buffer)
+		return -ENOMEM;
+
+	qcom_smd_channel_set_callback(channel, cb);
+	qcom_smd_channel_set_state(channel, SMD_CHANNEL_OPENING);
+	qcom_smd_channel_set_state(channel, SMD_CHANNEL_OPENED);
+
+	return 0;
+}
+
+/*
+ * Helper for closing and resetting a channel
+ */
+static void qcom_smd_channel_close(struct qcom_smd_channel *channel)
+{
+	qcom_smd_channel_set_callback(channel, NULL);
+
+	kfree(channel->bounce_buffer);
+	channel->bounce_buffer = NULL;
+
+	qcom_smd_channel_set_state(channel, SMD_CHANNEL_CLOSED);
+	qcom_smd_channel_reset(channel);
+}
+
+static struct qcom_smd_channel *
+qcom_smd_find_channel(struct qcom_smd_edge *edge, const char *name)
+{
+	struct qcom_smd_channel *channel;
+	struct qcom_smd_channel *ret = NULL;
+	unsigned long flags;
+	unsigned state;
+
+	spin_lock_irqsave(&edge->channels_lock, flags);
+	list_for_each_entry(channel, &edge->channels, list) {
+		if (strcmp(channel->name, name))
+			continue;
+
+		state = GET_RX_CHANNEL_INFO(channel, state);
+		if (state != SMD_CHANNEL_OPENING &&
+		    state != SMD_CHANNEL_OPENED)
+			continue;
+
+		ret = channel;
+		break;
+	}
+	spin_unlock_irqrestore(&edge->channels_lock, flags);
+
+	return ret;
+}
+
+static void __ept_release(struct kref *kref)
+{
+	struct rpmsg_endpoint *ept = container_of(kref, struct rpmsg_endpoint,
+						  refcount);
+	kfree(to_smd_endpoint(ept));
+}
+
+static struct rpmsg_endpoint *qcom_smd_create_ept(struct rpmsg_device *rpdev,
+						  rpmsg_rx_cb_t cb, void *priv,
+						  struct rpmsg_channel_info chinfo)
+{
+	struct qcom_smd_endpoint *qsept;
+	struct qcom_smd_channel *channel;
+	struct qcom_smd_device *qsdev = to_smd_device(&rpdev->dev);
+	struct qcom_smd_edge *edge = qsdev->edge;
+	struct rpmsg_endpoint *ept;
+	const char *name = chinfo.name;
+	int ret;
+
+	/* Wait up to HZ for the channel to appear */
+	ret = wait_event_interruptible_timeout(edge->new_channel_event,
+			(channel = qcom_smd_find_channel(edge, name)) != NULL,
+			HZ);
+	if (!ret)
+		return NULL;
+
+	if (channel->state != SMD_CHANNEL_CLOSED) {
+		dev_err(&rpdev->dev, "channel %s is busy\n", channel->name);
+		return NULL;
+	}
+
+	qsept = kzalloc(sizeof(*qsept), GFP_KERNEL);
+	if (!qsept)
+		return NULL;
+
+	ept = &qsept->ept;
+
+	kref_init(&ept->refcount);
+
+	ept->rpdev = rpdev;
+	ept->cb = cb;
+	ept->priv = priv;
+
+	channel->qsept = qsept;
+	qsept->qsch = channel;
+
+	ret = qcom_smd_channel_open(channel, cb);
+	if (ret)
+		goto free_ept;
+
+	return ept;
+
+free_ept:
+	channel->qsept = NULL;
+	kref_put(&ept->refcount, __ept_release);
+	return NULL;
+}
+
+static void qcom_smd_destroy_ept(struct rpmsg_endpoint *ept)
+{
+	struct qcom_smd_endpoint *qsept = to_smd_endpoint(ept);
+	struct qcom_smd_channel *ch = qsept->qsch;
+
+	qcom_smd_channel_close(ch);
+	ch->qsept = NULL;
+	kref_put(&ept->refcount, __ept_release);
+}
+
+static int qcom_smd_send(struct rpmsg_endpoint *ept, void *data, int len)
+{
+	struct qcom_smd_endpoint *qsept = to_smd_endpoint(ept);
+
+	return __qcom_smd_send(qsept->qsch, data, len, true);
+}
+
+static int qcom_smd_trysend(struct rpmsg_endpoint *ept, void *data, int len)
+{
+	struct qcom_smd_endpoint *qsept = to_smd_endpoint(ept);
+
+	return __qcom_smd_send(qsept->qsch, data, len, false);
+}
+
+/*
+ * Finds the device_node for the smd child interested in this channel.
+ */
+static struct device_node *qcom_smd_match_channel(struct device_node *edge_node,
+						  const char *channel)
+{
+	struct device_node *child;
+	const char *name;
+	const char *key;
+	int ret;
+
+	for_each_available_child_of_node(edge_node, child) {
+		key = "qcom,smd-channels";
+		ret = of_property_read_string(child, key, &name);
+		if (ret)
+			continue;
+
+		if (strcmp(name, channel) == 0)
+			return child;
+	}
+
+	return NULL;
+}
+
+static const struct rpmsg_channel qcom_smd_rpmsg_ops = {
+	.create_ept = qcom_smd_create_ept,
+	.destroy_ept = qcom_smd_destroy_ept,
+	.send = qcom_smd_send,
+	.trysend = qcom_smd_trysend,
+};
+
+/*
+ * Create a smd client device for channel that is being opened.
+ */
+static int qcom_smd_create_device(struct qcom_smd_channel *channel)
+{
+	struct qcom_smd_device *qsdev;
+	struct rpmsg_device *rpdev;
+	struct qcom_smd_edge *edge = channel->edge;
+
+	dev_dbg(&edge->dev, "registering '%s'\n", channel->name);
+
+	qsdev = kzalloc(sizeof(*qsdev), GFP_KERNEL);
+	if (!qsdev)
+		return -ENOMEM;
+
+	/* Link qsdev to our SMD edge */
+	qsdev->edge = edge;
+
+	/* Assign callbacks for rpmsg_channel */
+	qsdev->rpch = qcom_smd_rpmsg_ops;
+
+	/* Assign public information to the rpmsg_device */
+	rpdev = &qsdev->rpch.rpdev;
+	strncpy(rpdev->id.name, channel->name, RPMSG_NAME_SIZE);
+	rpdev->src = RPMSG_ADDR_ANY;
+	rpdev->dst = RPMSG_ADDR_ANY;
+
+	rpdev->dev.of_node = qcom_smd_match_channel(edge->of_node, channel->name);
+	rpdev->dev.parent = &edge->dev;
+
+	return rpmsg_register_device(rpdev);
+}
+
+/*
+ * Allocate the qcom_smd_channel object for a newly found smd channel,
+ * retrieving and validating the smem items involved.
+ */
+static struct qcom_smd_channel *qcom_smd_create_channel(struct qcom_smd_edge *edge,
+							unsigned smem_info_item,
+							unsigned smem_fifo_item,
+							char *name)
+{
+	struct qcom_smd_channel *channel;
+	size_t fifo_size;
+	size_t info_size;
+	void *fifo_base;
+	void *info;
+	int ret;
+
+	channel = devm_kzalloc(&edge->dev, sizeof(*channel), GFP_KERNEL);
+	if (!channel)
+		return ERR_PTR(-ENOMEM);
+
+	channel->edge = edge;
+	channel->name = devm_kstrdup(&edge->dev, name, GFP_KERNEL);
+	if (!channel->name)
+		return ERR_PTR(-ENOMEM);
+
+	mutex_init(&channel->tx_lock);
+	spin_lock_init(&channel->recv_lock);
+	init_waitqueue_head(&channel->fblockread_event);
+
+	info = qcom_smem_get(edge->remote_pid, smem_info_item, &info_size);
+	if (IS_ERR(info)) {
+		ret = PTR_ERR(info);
+		goto free_name_and_channel;
+	}
+
+	/*
+	 * Use the size of the item to figure out which channel info struct to
+	 * use.
+	 */
+	if (info_size == 2 * sizeof(struct smd_channel_info_word)) {
+		channel->info_word = info;
+	} else if (info_size == 2 * sizeof(struct smd_channel_info)) {
+		channel->info = info;
+	} else {
+		dev_err(&edge->dev,
+			"channel info of size %zu not supported\n", info_size);
+		ret = -EINVAL;
+		goto free_name_and_channel;
+	}
+
+	fifo_base = qcom_smem_get(edge->remote_pid, smem_fifo_item, &fifo_size);
+	if (IS_ERR(fifo_base)) {
+		ret =  PTR_ERR(fifo_base);
+		goto free_name_and_channel;
+	}
+
+	/* The channel consist of a rx and tx fifo of equal size */
+	fifo_size /= 2;
+
+	dev_dbg(&edge->dev, "new channel '%s' info-size: %zu fifo-size: %zu\n",
+			  name, info_size, fifo_size);
+
+	channel->tx_fifo = fifo_base;
+	channel->rx_fifo = fifo_base + fifo_size;
+	channel->fifo_size = fifo_size;
+
+	qcom_smd_channel_reset(channel);
+
+	return channel;
+
+free_name_and_channel:
+	devm_kfree(&edge->dev, channel->name);
+	devm_kfree(&edge->dev, channel);
+
+	return ERR_PTR(ret);
+}
+
+/*
+ * Scans the allocation table for any newly allocated channels, calls
+ * qcom_smd_create_channel() to create representations of these and add
+ * them to the edge's list of channels.
+ */
+static void qcom_channel_scan_worker(struct work_struct *work)
+{
+	struct qcom_smd_edge *edge = container_of(work, struct qcom_smd_edge, scan_work);
+	struct qcom_smd_alloc_entry *alloc_tbl;
+	struct qcom_smd_alloc_entry *entry;
+	struct qcom_smd_channel *channel;
+	unsigned long flags;
+	unsigned fifo_id;
+	unsigned info_id;
+	int tbl;
+	int i;
+	u32 eflags, cid;
+
+	for (tbl = 0; tbl < SMD_ALLOC_TBL_COUNT; tbl++) {
+		alloc_tbl = qcom_smem_get(edge->remote_pid,
+				    smem_items[tbl].alloc_tbl_id, NULL);
+		if (IS_ERR(alloc_tbl))
+			continue;
+
+		for (i = 0; i < SMD_ALLOC_TBL_SIZE; i++) {
+			entry = &alloc_tbl[i];
+			eflags = le32_to_cpu(entry->flags);
+			if (test_bit(i, edge->allocated[tbl]))
+				continue;
+
+			if (entry->ref_count == 0)
+				continue;
+
+			if (!entry->name[0])
+				continue;
+
+			if (!(eflags & SMD_CHANNEL_FLAGS_PACKET))
+				continue;
+
+			if ((eflags & SMD_CHANNEL_FLAGS_EDGE_MASK) != edge->edge_id)
+				continue;
+
+			cid = le32_to_cpu(entry->cid);
+			info_id = smem_items[tbl].info_base_id + cid;
+			fifo_id = smem_items[tbl].fifo_base_id + cid;
+
+			channel = qcom_smd_create_channel(edge, info_id, fifo_id, entry->name);
+			if (IS_ERR(channel))
+				continue;
+
+			spin_lock_irqsave(&edge->channels_lock, flags);
+			list_add(&channel->list, &edge->channels);
+			spin_unlock_irqrestore(&edge->channels_lock, flags);
+
+			dev_dbg(&edge->dev, "new channel found: '%s'\n", channel->name);
+			set_bit(i, edge->allocated[tbl]);
+
+			wake_up_interruptible(&edge->new_channel_event);
+		}
+	}
+
+	schedule_work(&edge->state_work);
+}
+
+/*
+ * This per edge worker scans smem for any new channels and register these. It
+ * then scans all registered channels for state changes that should be handled
+ * by creating or destroying smd client devices for the registered channels.
+ *
+ * LOCKING: edge->channels_lock only needs to cover the list operations, as the
+ * worker is killed before any channels are deallocated
+ */
+static void qcom_channel_state_worker(struct work_struct *work)
+{
+	struct qcom_smd_channel *channel;
+	struct qcom_smd_edge *edge = container_of(work,
+						  struct qcom_smd_edge,
+						  state_work);
+	struct rpmsg_channel_info chinfo;
+	unsigned remote_state;
+	unsigned long flags;
+
+	/*
+	 * Register a device for any closed channel where the remote processor
+	 * is showing interest in opening the channel.
+	 */
+	spin_lock_irqsave(&edge->channels_lock, flags);
+	list_for_each_entry(channel, &edge->channels, list) {
+		if (channel->state != SMD_CHANNEL_CLOSED)
+			continue;
+
+		remote_state = GET_RX_CHANNEL_INFO(channel, state);
+		if (remote_state != SMD_CHANNEL_OPENING &&
+		    remote_state != SMD_CHANNEL_OPENED)
+			continue;
+
+		if (channel->registered)
+			continue;
+
+		spin_unlock_irqrestore(&edge->channels_lock, flags);
+		qcom_smd_create_device(channel);
+		channel->registered = true;
+		spin_lock_irqsave(&edge->channels_lock, flags);
+
+		channel->registered = true;
+	}
+
+	/*
+	 * Unregister the device for any channel that is opened where the
+	 * remote processor is closing the channel.
+	 */
+	list_for_each_entry(channel, &edge->channels, list) {
+		if (channel->state != SMD_CHANNEL_OPENING &&
+		    channel->state != SMD_CHANNEL_OPENED)
+			continue;
+
+		remote_state = GET_RX_CHANNEL_INFO(channel, state);
+		if (remote_state == SMD_CHANNEL_OPENING ||
+		    remote_state == SMD_CHANNEL_OPENED)
+			continue;
+
+		spin_unlock_irqrestore(&edge->channels_lock, flags);
+
+		strncpy(chinfo.name, channel->name, sizeof(chinfo.name));
+		chinfo.src = RPMSG_ADDR_ANY;
+		chinfo.dst = RPMSG_ADDR_ANY;
+		rpmsg_unregister_device(&edge->dev, &chinfo);
+		channel->registered = false;
+		spin_lock_irqsave(&edge->channels_lock, flags);
+	}
+	spin_unlock_irqrestore(&edge->channels_lock, flags);
+}
+
+/*
+ * Parses an of_node describing an edge.
+ */
+static int qcom_smd_parse_edge(struct device *dev,
+			       struct device_node *node,
+			       struct qcom_smd_edge *edge)
+{
+	struct device_node *syscon_np;
+	const char *key;
+	int irq;
+	int ret;
+
+	INIT_LIST_HEAD(&edge->channels);
+	spin_lock_init(&edge->channels_lock);
+
+	INIT_WORK(&edge->scan_work, qcom_channel_scan_worker);
+	INIT_WORK(&edge->state_work, qcom_channel_state_worker);
+
+	edge->of_node = of_node_get(node);
+
+	key = "qcom,smd-edge";
+	ret = of_property_read_u32(node, key, &edge->edge_id);
+	if (ret) {
+		dev_err(dev, "edge missing %s property\n", key);
+		return -EINVAL;
+	}
+
+	edge->remote_pid = QCOM_SMEM_HOST_ANY;
+	key = "qcom,remote-pid";
+	of_property_read_u32(node, key, &edge->remote_pid);
+
+	syscon_np = of_parse_phandle(node, "qcom,ipc", 0);
+	if (!syscon_np) {
+		dev_err(dev, "no qcom,ipc node\n");
+		return -ENODEV;
+	}
+
+	edge->ipc_regmap = syscon_node_to_regmap(syscon_np);
+	if (IS_ERR(edge->ipc_regmap))
+		return PTR_ERR(edge->ipc_regmap);
+
+	key = "qcom,ipc";
+	ret = of_property_read_u32_index(node, key, 1, &edge->ipc_offset);
+	if (ret < 0) {
+		dev_err(dev, "no offset in %s\n", key);
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32_index(node, key, 2, &edge->ipc_bit);
+	if (ret < 0) {
+		dev_err(dev, "no bit in %s\n", key);
+		return -EINVAL;
+	}
+
+	irq = irq_of_parse_and_map(node, 0);
+	if (irq < 0) {
+		dev_err(dev, "required smd interrupt missing\n");
+		return -EINVAL;
+	}
+
+	ret = devm_request_irq(dev, irq,
+			       qcom_smd_edge_intr, IRQF_TRIGGER_RISING,
+			       node->name, edge);
+	if (ret) {
+		dev_err(dev, "failed to request smd irq\n");
+		return ret;
+	}
+
+	edge->irq = irq;
+
+	return 0;
+}
+
+/*
+ * Release function for an edge.
+  * Reset the state of each associated channel and free the edge context.
+ */
+static void qcom_smd_edge_release(struct device *dev)
+{
+	struct qcom_smd_channel *channel;
+	struct qcom_smd_edge *edge = to_smd_edge(dev);
+
+	list_for_each_entry(channel, &edge->channels, list) {
+		SET_RX_CHANNEL_INFO(channel, state, SMD_CHANNEL_CLOSED);
+		SET_RX_CHANNEL_INFO(channel, head, 0);
+		SET_RX_CHANNEL_INFO(channel, tail, 0);
+	}
+
+	kfree(edge);
+}
+
+/**
+ * qcom_smd_register_edge() - register an edge based on an device_node
+ * @parent:    parent device for the edge
+ * @node:      device_node describing the edge
+ *
+ * Returns an edge reference, or negative ERR_PTR() on failure.
+ */
+struct qcom_smd_edge *qcom_smd_register_edge(struct device *parent,
+					     struct device_node *node)
+{
+	struct qcom_smd_edge *edge;
+	int ret;
+
+	edge = kzalloc(sizeof(*edge), GFP_KERNEL);
+	if (!edge)
+		return ERR_PTR(-ENOMEM);
+
+	init_waitqueue_head(&edge->new_channel_event);
+
+	edge->dev.parent = parent;
+	edge->dev.release = qcom_smd_edge_release;
+	dev_set_name(&edge->dev, "%s:%s", dev_name(parent), node->name);
+	ret = device_register(&edge->dev);
+	if (ret) {
+		pr_err("failed to register smd edge\n");
+		return ERR_PTR(ret);
+	}
+
+	ret = qcom_smd_parse_edge(&edge->dev, node, edge);
+	if (ret) {
+		dev_err(&edge->dev, "failed to parse smd edge\n");
+		goto unregister_dev;
+	}
+
+	schedule_work(&edge->scan_work);
+
+	return edge;
+
+unregister_dev:
+	put_device(&edge->dev);
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL(qcom_smd_register_edge);
+
+static int qcom_smd_remove_device(struct device *dev, void *data)
+{
+	device_unregister(dev);
+
+	return 0;
+}
+
+/**
+ * qcom_smd_unregister_edge() - release an edge and its children
+ * @edge:      edge reference acquired from qcom_smd_register_edge
+ */
+int qcom_smd_unregister_edge(struct qcom_smd_edge *edge)
+{
+	int ret;
+
+	disable_irq(edge->irq);
+	cancel_work_sync(&edge->scan_work);
+	cancel_work_sync(&edge->state_work);
+
+	ret = device_for_each_child(&edge->dev, NULL, qcom_smd_remove_device);
+	if (ret)
+		dev_warn(&edge->dev, "can't remove smd device: %d\n", ret);
+
+	device_unregister(&edge->dev);
+
+	return 0;
+}
+EXPORT_SYMBOL(qcom_smd_unregister_edge);
+
+static int qcom_smd_probe(struct platform_device *pdev)
+{
+	struct device_node *node;
+	void *p;
+
+	/* Wait for smem */
+	p = qcom_smem_get(QCOM_SMEM_HOST_ANY, smem_items[0].alloc_tbl_id, NULL);
+	if (PTR_ERR(p) == -EPROBE_DEFER)
+		return PTR_ERR(p);
+
+	for_each_available_child_of_node(pdev->dev.of_node, node)
+		qcom_smd_register_edge(&pdev->dev, node);
+
+	return 0;
+}
+
+static int qcom_smd_remove_edge(struct device *dev, void *data)
+{
+	struct qcom_smd_edge *edge = to_smd_edge(dev);
+
+	return qcom_smd_unregister_edge(edge);
+}
+
+/*
+ * Shut down all smd clients by making sure that each edge stops processing
+ * events and scanning for new channels, then call destroy on the devices.
+ */
+static int qcom_smd_remove(struct platform_device *pdev)
+{
+	int ret;
+
+	ret = device_for_each_child(&pdev->dev, NULL, qcom_smd_remove_edge);
+	if (ret)
+		dev_warn(&pdev->dev, "can't remove smd device: %d\n", ret);
+
+	return ret;
+}
+
+static const struct of_device_id qcom_smd_of_match[] = {
+	{ .compatible = "qcom,smd" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, qcom_smd_of_match);
+
+static struct platform_driver qcom_smd_driver = {
+	.probe = qcom_smd_probe,
+	.remove = qcom_smd_remove,
+	.driver = {
+		.name = "qcom-smd",
+		.of_match_table = qcom_smd_of_match,
+	},
+};
+
+static int __init qcom_smd_init(void)
+{
+	return platform_driver_register(&qcom_smd_driver);
+}
+subsys_initcall(qcom_smd_init);
+
+static void __exit qcom_smd_exit(void)
+{
+	platform_driver_unregister(&qcom_smd_driver);
+}
+module_exit(qcom_smd_exit);
+
+MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@sonymobile.com>");
+MODULE_DESCRIPTION("Qualcomm Shared Memory Driver");
+MODULE_LICENSE("GPL v2");
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* RE: [PATCH 03/14] rpmsg: rpmsg_send() operations takes rpmsg_endpoint
  2016-08-16  0:17   ` Bjorn Andersson
  (?)
@ 2016-08-18  7:36     ` Loic PALLARDY
  -1 siblings, 0 replies; 54+ messages in thread
From: Loic PALLARDY @ 2016-08-18  7:36 UTC (permalink / raw)
  To: Bjorn Andersson, Ohad Ben-Cohen
  Cc: linux-remoteproc, linux-arm-msm, linux-arm-kernel, linux-kernel



> -----Original Message-----
> From: linux-remoteproc-owner@vger.kernel.org [mailto:linux-remoteproc-
> owner@vger.kernel.org] On Behalf Of Bjorn Andersson
> Sent: Tuesday, August 16, 2016 2:17 AM
> To: Ohad Ben-Cohen <ohad@wizery.com>; Bjorn Andersson
> <bjorn.andersson@linaro.org>
> Cc: linux-remoteproc@vger.kernel.org; linux-arm-msm@vger.kernel.org;
> linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org
> Subject: [PATCH 03/14] rpmsg: rpmsg_send() operations takes
> rpmsg_endpoint
> 
> The rpmsg_send() operations has been taking a rpmsg_device, but this
> forces users of secondary rpmsg_endpoints to use the rpmsg_sendto()
> interface - by extracting source and destination from the given data
> structures. If we instead pass the rpmsg_endpoint to these functions a
> service can use rpmsg_sendto() to respond to messages, even on secondary
> endpoints.
> 
> In addition this would allow us to support operations on multiple
> channels in future backends that does not support off-channel
> operations.
> 
Hi Bjorn,

This patch is modifying rpmsg API by using rpmsg_endpoint as argument
instead of rpmsg_device.
But associated port of rpmsg_client_sample driver is missing in your patch series.

Please find inline few comments.

> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> ---
>  drivers/rpmsg/virtio_rpmsg_bus.c |  4 +--
>  include/linux/rpmsg.h            | 70 +++++++++++++++++++++++-----------------
>  2 files changed, 42 insertions(+), 32 deletions(-)
> 
> diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c
> b/drivers/rpmsg/virtio_rpmsg_bus.c
> index c4bd89ea7681..1b63f4b7c2bd 100644
> --- a/drivers/rpmsg/virtio_rpmsg_bus.c
> +++ b/drivers/rpmsg/virtio_rpmsg_bus.c
> @@ -382,7 +382,7 @@ static int rpmsg_dev_probe(struct device *dev)
>  		nsm.addr = rpdev->src;

Since endpoint is now used to indicate source, I'm wondering if it is possible
to suppress src field from struct rpmsg_channel and rely only on endpoint addr?
Else maybe confusing (which src addr used at the end: rpdev or ept?)

>  		nsm.flags = RPMSG_NS_CREATE;
> 
> -		err = rpmsg_sendto(rpdev, &nsm, sizeof(nsm),
> RPMSG_NS_ADDR);
> +		err = rpmsg_sendto(rpdev->ept, &nsm, sizeof(nsm),
> RPMSG_NS_ADDR);
>  		if (err)
>  			dev_err(dev, "failed to announce service %d\n", err);
>  	}
> @@ -407,7 +407,7 @@ static int rpmsg_dev_remove(struct device *dev)
>  		nsm.addr = rpdev->src;
>  		nsm.flags = RPMSG_NS_DESTROY;
> 
> -		err = rpmsg_sendto(rpdev, &nsm, sizeof(nsm),
> RPMSG_NS_ADDR);
> +		err = rpmsg_sendto(rpdev->ept, &nsm, sizeof(nsm),
> RPMSG_NS_ADDR);
>  		if (err)
>  			dev_err(dev, "failed to announce service %d\n", err);
>  	}
> diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
> index 2b97c711a5e3..88e302c011e6 100644
> --- a/include/linux/rpmsg.h
> +++ b/include/linux/rpmsg.h
> @@ -193,13 +193,14 @@ rpmsg_send_offchannel_raw(struct
> rpmsg_channel *, u32, u32, void *, int, bool);
> 
>  /**
>   * rpmsg_send() - send a message across to the remote processor
> - * @rpdev: the rpmsg channel
> + * @ept: the rpmsg endpoint
>   * @data: payload of message
>   * @len: length of payload
>   *
> - * This function sends @data of length @len on the @rpdev channel.
> - * The message will be sent to the remote processor which the @rpdev
> - * channel belongs to, using @rpdev's source and destination addresses.
> + * This function sends @data of length @len on the @ept endpoint.
> + * The message will be sent to the remote processor which the @ept
> + * endpoint belongs to, using @ept's address and its associated rpmsg
> + * device destination addresses.
>   * In case there are no TX buffers available, the function will block until
>   * one becomes available, or a timeout of 15 seconds elapses. When the
> latter
>   * happens, -ERESTARTSYS is returned.
> @@ -208,23 +209,24 @@ rpmsg_send_offchannel_raw(struct
> rpmsg_channel *, u32, u32, void *, int, bool);
>   *
>   * Returns 0 on success and an appropriate error value on failure.
>   */
> -static inline int rpmsg_send(struct rpmsg_channel *rpdev, void *data, int
> len)
> +static inline int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int
> len)
>  {
> -	u32 src = rpdev->src, dst = rpdev->dst;
> +	struct rpmsg_channel *rpdev = ept->rpdev;
> +	u32 src = ept->addr, dst = rpdev->dst;
As this function is part of rpmsg API, it will be good to verify pointers before use.
> 
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
>  }
> 
>  /**
>   * rpmsg_sendto() - send a message across to the remote processor, specify
> dst
> - * @rpdev: the rpmsg channel
> + * @ept: the rpmsg endpoint
>   * @data: payload of message
>   * @len: length of payload
>   * @dst: destination address
>   *
>   * This function sends @data of length @len to the remote @dst address.
> - * The message will be sent to the remote processor which the @rpdev
> - * channel belongs to, using @rpdev's source address.
> + * The message will be sent to the remote processor which the @ept
> + * endpoint belongs to, using @ept's address as source.
>   * In case there are no TX buffers available, the function will block until
>   * one becomes available, or a timeout of 15 seconds elapses. When the
> latter
>   * happens, -ERESTARTSYS is returned.
> @@ -234,16 +236,17 @@ static inline int rpmsg_send(struct rpmsg_channel
> *rpdev, void *data, int len)
>   * Returns 0 on success and an appropriate error value on failure.
>   */
>  static inline
> -int rpmsg_sendto(struct rpmsg_channel *rpdev, void *data, int len, u32 dst)
> +int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
>  {
> -	u32 src = rpdev->src;
> +	struct rpmsg_channel *rpdev = ept->rpdev;
> +	u32 src = ept->addr;
ditto

> 
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
>  }
> 
>  /**
>   * rpmsg_send_offchannel() - send a message using explicit src/dst
> addresses
> - * @rpdev: the rpmsg channel
> + * @ept: the rpmsg endpoint
>   * @src: source address
>   * @dst: destination address
>   * @data: payload of message
> @@ -251,8 +254,8 @@ int rpmsg_sendto(struct rpmsg_channel *rpdev, void
> *data, int len, u32 dst)
>   *
>   * This function sends @data of length @len to the remote @dst address,
>   * and uses @src as the source address.
> - * The message will be sent to the remote processor which the @rpdev
> - * channel belongs to.
> + * The message will be sent to the remote processor which the @ept
> + * endpoint belongs to.
>   * In case there are no TX buffers available, the function will block until
>   * one becomes available, or a timeout of 15 seconds elapses. When the
> latter
>   * happens, -ERESTARTSYS is returned.
> @@ -262,21 +265,24 @@ int rpmsg_sendto(struct rpmsg_channel *rpdev,
> void *data, int len, u32 dst)
>   * Returns 0 on success and an appropriate error value on failure.
>   */
>  static inline
> -int rpmsg_send_offchannel(struct rpmsg_channel *rpdev, u32 src, u32 dst,
> +int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
>  			  void *data, int len)
>  {
> +	struct rpmsg_channel *rpdev = ept->rpdev;
ditto
> +
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
>  }
> 
>  /**
>   * rpmsg_send() - send a message across to the remote processor
Function name and description not aligned with code.
Should be rpmsg_trysend
May be in another patch...

> - * @rpdev: the rpmsg channel
> + * @ept: the rpmsg endpoint
>   * @data: payload of message
>   * @len: length of payload
>   *
> - * This function sends @data of length @len on the @rpdev channel.
> - * The message will be sent to the remote processor which the @rpdev
> - * channel belongs to, using @rpdev's source and destination addresses.
> + * This function sends @data of length @len on the @ept endpoint.
> + * The message will be sent to the remote processor which the @ept
> + * endpoint belongs to, using @ept's addres as source and its associated
> + * rpdev's address as destination.
>   * In case there are no TX buffers available, the function will immediately
>   * return -ENOMEM without waiting until one becomes available.
>   *
> @@ -285,23 +291,24 @@ int rpmsg_send_offchannel(struct rpmsg_channel
> *rpdev, u32 src, u32 dst,
>   * Returns 0 on success and an appropriate error value on failure.
>   */
>  static inline
> -int rpmsg_trysend(struct rpmsg_channel *rpdev, void *data, int len)
> +int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
>  {
> -	u32 src = rpdev->src, dst = rpdev->dst;
> +	struct rpmsg_channel *rpdev = ept->rpdev;
> +	u32 src = ept->addr, dst = rpdev->dst;
Pointer check before use
> 
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
>  }
> 
>  /**
>   * rpmsg_sendto() - send a message across to the remote processor, specify
> dst
Function name should be rpmsg_trysendto
> - * @rpdev: the rpmsg channel
> + * @ept: the rpmsg endpoint
>   * @data: payload of message
>   * @len: length of payload
>   * @dst: destination address
>   *
>   * This function sends @data of length @len to the remote @dst address.
> - * The message will be sent to the remote processor which the @rpdev
> - * channel belongs to, using @rpdev's source address.
> + * The message will be sent to the remote processor which the @ept
> + * endpoint belongs to, using @ept's address as source.
>   * In case there are no TX buffers available, the function will immediately
>   * return -ENOMEM without waiting until one becomes available.
>   *
> @@ -310,16 +317,17 @@ int rpmsg_trysend(struct rpmsg_channel *rpdev,
> void *data, int len)
>   * Returns 0 on success and an appropriate error value on failure.
>   */
>  static inline
> -int rpmsg_trysendto(struct rpmsg_channel *rpdev, void *data, int len, u32
> dst)
> +int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32
> dst)
>  {
> -	u32 src = rpdev->src;
> +	struct rpmsg_channel *rpdev = ept->rpdev;
> +	u32 src = ept->addr;
Check pointer before use
> 
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
>  }
> 
>  /**
>   * rpmsg_send_offchannel() - send a message using explicit src/dst
> addresses
Description for rpmsg_trysend_offchannel...

> - * @rpdev: the rpmsg channel
> + * @ept: the rpmsg endpoint
>   * @src: source address
>   * @dst: destination address
>   * @data: payload of message
> @@ -327,8 +335,8 @@ int rpmsg_trysendto(struct rpmsg_channel *rpdev,
> void *data, int len, u32 dst)
>   *
>   * This function sends @data of length @len to the remote @dst address,
>   * and uses @src as the source address.
> - * The message will be sent to the remote processor which the @rpdev
> - * channel belongs to.
> + * The message will be sent to the remote processor which the @ept
> + * endpoint belongs to.
>   * In case there are no TX buffers available, the function will immediately
>   * return -ENOMEM without waiting until one becomes available.
>   *
> @@ -337,9 +345,11 @@ int rpmsg_trysendto(struct rpmsg_channel *rpdev,
> void *data, int len, u32 dst)
>   * Returns 0 on success and an appropriate error value on failure.
>   */
>  static inline
> -int rpmsg_trysend_offchannel(struct rpmsg_channel *rpdev, u32 src, u32
> dst,
> +int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32
> dst,
>  			     void *data, int len)
>  {
> +	struct rpmsg_channel *rpdev = ept->rpdev;
> +
Point check before use
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
>  }

Regards,
Loic 

> 
> --
> 2.5.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-remoteproc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 54+ messages in thread

* RE: [PATCH 03/14] rpmsg: rpmsg_send() operations takes rpmsg_endpoint
@ 2016-08-18  7:36     ` Loic PALLARDY
  0 siblings, 0 replies; 54+ messages in thread
From: Loic PALLARDY @ 2016-08-18  7:36 UTC (permalink / raw)
  To: Bjorn Andersson, Ohad Ben-Cohen
  Cc: linux-remoteproc, linux-arm-msm, linux-arm-kernel, linux-kernel



> -----Original Message-----
> From: linux-remoteproc-owner@vger.kernel.org [mailto:linux-remoteproc-
> owner@vger.kernel.org] On Behalf Of Bjorn Andersson
> Sent: Tuesday, August 16, 2016 2:17 AM
> To: Ohad Ben-Cohen <ohad@wizery.com>; Bjorn Andersson
> <bjorn.andersson@linaro.org>
> Cc: linux-remoteproc@vger.kernel.org; linux-arm-msm@vger.kernel.org;
> linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org
> Subject: [PATCH 03/14] rpmsg: rpmsg_send() operations takes
> rpmsg_endpoint
> 
> The rpmsg_send() operations has been taking a rpmsg_device, but this
> forces users of secondary rpmsg_endpoints to use the rpmsg_sendto()
> interface - by extracting source and destination from the given data
> structures. If we instead pass the rpmsg_endpoint to these functions a
> service can use rpmsg_sendto() to respond to messages, even on secondary
> endpoints.
> 
> In addition this would allow us to support operations on multiple
> channels in future backends that does not support off-channel
> operations.
> 
Hi Bjorn,

This patch is modifying rpmsg API by using rpmsg_endpoint as argument
instead of rpmsg_device.
But associated port of rpmsg_client_sample driver is missing in your patch series.

Please find inline few comments.

> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> ---
>  drivers/rpmsg/virtio_rpmsg_bus.c |  4 +--
>  include/linux/rpmsg.h            | 70 +++++++++++++++++++++++-----------------
>  2 files changed, 42 insertions(+), 32 deletions(-)
> 
> diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c
> b/drivers/rpmsg/virtio_rpmsg_bus.c
> index c4bd89ea7681..1b63f4b7c2bd 100644
> --- a/drivers/rpmsg/virtio_rpmsg_bus.c
> +++ b/drivers/rpmsg/virtio_rpmsg_bus.c
> @@ -382,7 +382,7 @@ static int rpmsg_dev_probe(struct device *dev)
>  		nsm.addr = rpdev->src;

Since endpoint is now used to indicate source, I'm wondering if it is possible
to suppress src field from struct rpmsg_channel and rely only on endpoint addr?
Else maybe confusing (which src addr used at the end: rpdev or ept?)

>  		nsm.flags = RPMSG_NS_CREATE;
> 
> -		err = rpmsg_sendto(rpdev, &nsm, sizeof(nsm),
> RPMSG_NS_ADDR);
> +		err = rpmsg_sendto(rpdev->ept, &nsm, sizeof(nsm),
> RPMSG_NS_ADDR);
>  		if (err)
>  			dev_err(dev, "failed to announce service %d\n", err);
>  	}
> @@ -407,7 +407,7 @@ static int rpmsg_dev_remove(struct device *dev)
>  		nsm.addr = rpdev->src;
>  		nsm.flags = RPMSG_NS_DESTROY;
> 
> -		err = rpmsg_sendto(rpdev, &nsm, sizeof(nsm),
> RPMSG_NS_ADDR);
> +		err = rpmsg_sendto(rpdev->ept, &nsm, sizeof(nsm),
> RPMSG_NS_ADDR);
>  		if (err)
>  			dev_err(dev, "failed to announce service %d\n", err);
>  	}
> diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
> index 2b97c711a5e3..88e302c011e6 100644
> --- a/include/linux/rpmsg.h
> +++ b/include/linux/rpmsg.h
> @@ -193,13 +193,14 @@ rpmsg_send_offchannel_raw(struct
> rpmsg_channel *, u32, u32, void *, int, bool);
> 
>  /**
>   * rpmsg_send() - send a message across to the remote processor
> - * @rpdev: the rpmsg channel
> + * @ept: the rpmsg endpoint
>   * @data: payload of message
>   * @len: length of payload
>   *
> - * This function sends @data of length @len on the @rpdev channel.
> - * The message will be sent to the remote processor which the @rpdev
> - * channel belongs to, using @rpdev's source and destination addresses.
> + * This function sends @data of length @len on the @ept endpoint.
> + * The message will be sent to the remote processor which the @ept
> + * endpoint belongs to, using @ept's address and its associated rpmsg
> + * device destination addresses.
>   * In case there are no TX buffers available, the function will block until
>   * one becomes available, or a timeout of 15 seconds elapses. When the
> latter
>   * happens, -ERESTARTSYS is returned.
> @@ -208,23 +209,24 @@ rpmsg_send_offchannel_raw(struct
> rpmsg_channel *, u32, u32, void *, int, bool);
>   *
>   * Returns 0 on success and an appropriate error value on failure.
>   */
> -static inline int rpmsg_send(struct rpmsg_channel *rpdev, void *data, int
> len)
> +static inline int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int
> len)
>  {
> -	u32 src = rpdev->src, dst = rpdev->dst;
> +	struct rpmsg_channel *rpdev = ept->rpdev;
> +	u32 src = ept->addr, dst = rpdev->dst;
As this function is part of rpmsg API, it will be good to verify pointers before use.
> 
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
>  }
> 
>  /**
>   * rpmsg_sendto() - send a message across to the remote processor, specify
> dst
> - * @rpdev: the rpmsg channel
> + * @ept: the rpmsg endpoint
>   * @data: payload of message
>   * @len: length of payload
>   * @dst: destination address
>   *
>   * This function sends @data of length @len to the remote @dst address.
> - * The message will be sent to the remote processor which the @rpdev
> - * channel belongs to, using @rpdev's source address.
> + * The message will be sent to the remote processor which the @ept
> + * endpoint belongs to, using @ept's address as source.
>   * In case there are no TX buffers available, the function will block until
>   * one becomes available, or a timeout of 15 seconds elapses. When the
> latter
>   * happens, -ERESTARTSYS is returned.
> @@ -234,16 +236,17 @@ static inline int rpmsg_send(struct rpmsg_channel
> *rpdev, void *data, int len)
>   * Returns 0 on success and an appropriate error value on failure.
>   */
>  static inline
> -int rpmsg_sendto(struct rpmsg_channel *rpdev, void *data, int len, u32 dst)
> +int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
>  {
> -	u32 src = rpdev->src;
> +	struct rpmsg_channel *rpdev = ept->rpdev;
> +	u32 src = ept->addr;
ditto

> 
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
>  }
> 
>  /**
>   * rpmsg_send_offchannel() - send a message using explicit src/dst
> addresses
> - * @rpdev: the rpmsg channel
> + * @ept: the rpmsg endpoint
>   * @src: source address
>   * @dst: destination address
>   * @data: payload of message
> @@ -251,8 +254,8 @@ int rpmsg_sendto(struct rpmsg_channel *rpdev, void
> *data, int len, u32 dst)
>   *
>   * This function sends @data of length @len to the remote @dst address,
>   * and uses @src as the source address.
> - * The message will be sent to the remote processor which the @rpdev
> - * channel belongs to.
> + * The message will be sent to the remote processor which the @ept
> + * endpoint belongs to.
>   * In case there are no TX buffers available, the function will block until
>   * one becomes available, or a timeout of 15 seconds elapses. When the
> latter
>   * happens, -ERESTARTSYS is returned.
> @@ -262,21 +265,24 @@ int rpmsg_sendto(struct rpmsg_channel *rpdev,
> void *data, int len, u32 dst)
>   * Returns 0 on success and an appropriate error value on failure.
>   */
>  static inline
> -int rpmsg_send_offchannel(struct rpmsg_channel *rpdev, u32 src, u32 dst,
> +int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
>  			  void *data, int len)
>  {
> +	struct rpmsg_channel *rpdev = ept->rpdev;
ditto
> +
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
>  }
> 
>  /**
>   * rpmsg_send() - send a message across to the remote processor
Function name and description not aligned with code.
Should be rpmsg_trysend
May be in another patch...

> - * @rpdev: the rpmsg channel
> + * @ept: the rpmsg endpoint
>   * @data: payload of message
>   * @len: length of payload
>   *
> - * This function sends @data of length @len on the @rpdev channel.
> - * The message will be sent to the remote processor which the @rpdev
> - * channel belongs to, using @rpdev's source and destination addresses.
> + * This function sends @data of length @len on the @ept endpoint.
> + * The message will be sent to the remote processor which the @ept
> + * endpoint belongs to, using @ept's addres as source and its associated
> + * rpdev's address as destination.
>   * In case there are no TX buffers available, the function will immediately
>   * return -ENOMEM without waiting until one becomes available.
>   *
> @@ -285,23 +291,24 @@ int rpmsg_send_offchannel(struct rpmsg_channel
> *rpdev, u32 src, u32 dst,
>   * Returns 0 on success and an appropriate error value on failure.
>   */
>  static inline
> -int rpmsg_trysend(struct rpmsg_channel *rpdev, void *data, int len)
> +int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
>  {
> -	u32 src = rpdev->src, dst = rpdev->dst;
> +	struct rpmsg_channel *rpdev = ept->rpdev;
> +	u32 src = ept->addr, dst = rpdev->dst;
Pointer check before use
> 
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
>  }
> 
>  /**
>   * rpmsg_sendto() - send a message across to the remote processor, specify
> dst
Function name should be rpmsg_trysendto
> - * @rpdev: the rpmsg channel
> + * @ept: the rpmsg endpoint
>   * @data: payload of message
>   * @len: length of payload
>   * @dst: destination address
>   *
>   * This function sends @data of length @len to the remote @dst address.
> - * The message will be sent to the remote processor which the @rpdev
> - * channel belongs to, using @rpdev's source address.
> + * The message will be sent to the remote processor which the @ept
> + * endpoint belongs to, using @ept's address as source.
>   * In case there are no TX buffers available, the function will immediately
>   * return -ENOMEM without waiting until one becomes available.
>   *
> @@ -310,16 +317,17 @@ int rpmsg_trysend(struct rpmsg_channel *rpdev,
> void *data, int len)
>   * Returns 0 on success and an appropriate error value on failure.
>   */
>  static inline
> -int rpmsg_trysendto(struct rpmsg_channel *rpdev, void *data, int len, u32
> dst)
> +int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32
> dst)
>  {
> -	u32 src = rpdev->src;
> +	struct rpmsg_channel *rpdev = ept->rpdev;
> +	u32 src = ept->addr;
Check pointer before use
> 
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
>  }
> 
>  /**
>   * rpmsg_send_offchannel() - send a message using explicit src/dst
> addresses
Description for rpmsg_trysend_offchannel...

> - * @rpdev: the rpmsg channel
> + * @ept: the rpmsg endpoint
>   * @src: source address
>   * @dst: destination address
>   * @data: payload of message
> @@ -327,8 +335,8 @@ int rpmsg_trysendto(struct rpmsg_channel *rpdev,
> void *data, int len, u32 dst)
>   *
>   * This function sends @data of length @len to the remote @dst address,
>   * and uses @src as the source address.
> - * The message will be sent to the remote processor which the @rpdev
> - * channel belongs to.
> + * The message will be sent to the remote processor which the @ept
> + * endpoint belongs to.
>   * In case there are no TX buffers available, the function will immediately
>   * return -ENOMEM without waiting until one becomes available.
>   *
> @@ -337,9 +345,11 @@ int rpmsg_trysendto(struct rpmsg_channel *rpdev,
> void *data, int len, u32 dst)
>   * Returns 0 on success and an appropriate error value on failure.
>   */
>  static inline
> -int rpmsg_trysend_offchannel(struct rpmsg_channel *rpdev, u32 src, u32
> dst,
> +int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32
> dst,
>  			     void *data, int len)
>  {
> +	struct rpmsg_channel *rpdev = ept->rpdev;
> +
Point check before use
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
>  }

Regards,
Loic 

> 
> --
> 2.5.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-remoteproc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 54+ messages in thread

* [PATCH 03/14] rpmsg: rpmsg_send() operations takes rpmsg_endpoint
@ 2016-08-18  7:36     ` Loic PALLARDY
  0 siblings, 0 replies; 54+ messages in thread
From: Loic PALLARDY @ 2016-08-18  7:36 UTC (permalink / raw)
  To: linux-arm-kernel



> -----Original Message-----
> From: linux-remoteproc-owner at vger.kernel.org [mailto:linux-remoteproc-
> owner at vger.kernel.org] On Behalf Of Bjorn Andersson
> Sent: Tuesday, August 16, 2016 2:17 AM
> To: Ohad Ben-Cohen <ohad@wizery.com>; Bjorn Andersson
> <bjorn.andersson@linaro.org>
> Cc: linux-remoteproc at vger.kernel.org; linux-arm-msm at vger.kernel.org;
> linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org
> Subject: [PATCH 03/14] rpmsg: rpmsg_send() operations takes
> rpmsg_endpoint
> 
> The rpmsg_send() operations has been taking a rpmsg_device, but this
> forces users of secondary rpmsg_endpoints to use the rpmsg_sendto()
> interface - by extracting source and destination from the given data
> structures. If we instead pass the rpmsg_endpoint to these functions a
> service can use rpmsg_sendto() to respond to messages, even on secondary
> endpoints.
> 
> In addition this would allow us to support operations on multiple
> channels in future backends that does not support off-channel
> operations.
> 
Hi Bjorn,

This patch is modifying rpmsg API by using rpmsg_endpoint as argument
instead of rpmsg_device.
But associated port of rpmsg_client_sample driver is missing in your patch series.

Please find inline few comments.

> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> ---
>  drivers/rpmsg/virtio_rpmsg_bus.c |  4 +--
>  include/linux/rpmsg.h            | 70 +++++++++++++++++++++++-----------------
>  2 files changed, 42 insertions(+), 32 deletions(-)
> 
> diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c
> b/drivers/rpmsg/virtio_rpmsg_bus.c
> index c4bd89ea7681..1b63f4b7c2bd 100644
> --- a/drivers/rpmsg/virtio_rpmsg_bus.c
> +++ b/drivers/rpmsg/virtio_rpmsg_bus.c
> @@ -382,7 +382,7 @@ static int rpmsg_dev_probe(struct device *dev)
>  		nsm.addr = rpdev->src;

Since endpoint is now used to indicate source, I'm wondering if it is possible
to suppress src field from struct rpmsg_channel and rely only on endpoint addr?
Else maybe confusing (which src addr used at the end: rpdev or ept?)

>  		nsm.flags = RPMSG_NS_CREATE;
> 
> -		err = rpmsg_sendto(rpdev, &nsm, sizeof(nsm),
> RPMSG_NS_ADDR);
> +		err = rpmsg_sendto(rpdev->ept, &nsm, sizeof(nsm),
> RPMSG_NS_ADDR);
>  		if (err)
>  			dev_err(dev, "failed to announce service %d\n", err);
>  	}
> @@ -407,7 +407,7 @@ static int rpmsg_dev_remove(struct device *dev)
>  		nsm.addr = rpdev->src;
>  		nsm.flags = RPMSG_NS_DESTROY;
> 
> -		err = rpmsg_sendto(rpdev, &nsm, sizeof(nsm),
> RPMSG_NS_ADDR);
> +		err = rpmsg_sendto(rpdev->ept, &nsm, sizeof(nsm),
> RPMSG_NS_ADDR);
>  		if (err)
>  			dev_err(dev, "failed to announce service %d\n", err);
>  	}
> diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
> index 2b97c711a5e3..88e302c011e6 100644
> --- a/include/linux/rpmsg.h
> +++ b/include/linux/rpmsg.h
> @@ -193,13 +193,14 @@ rpmsg_send_offchannel_raw(struct
> rpmsg_channel *, u32, u32, void *, int, bool);
> 
>  /**
>   * rpmsg_send() - send a message across to the remote processor
> - * @rpdev: the rpmsg channel
> + * @ept: the rpmsg endpoint
>   * @data: payload of message
>   * @len: length of payload
>   *
> - * This function sends @data of length @len on the @rpdev channel.
> - * The message will be sent to the remote processor which the @rpdev
> - * channel belongs to, using @rpdev's source and destination addresses.
> + * This function sends @data of length @len on the @ept endpoint.
> + * The message will be sent to the remote processor which the @ept
> + * endpoint belongs to, using @ept's address and its associated rpmsg
> + * device destination addresses.
>   * In case there are no TX buffers available, the function will block until
>   * one becomes available, or a timeout of 15 seconds elapses. When the
> latter
>   * happens, -ERESTARTSYS is returned.
> @@ -208,23 +209,24 @@ rpmsg_send_offchannel_raw(struct
> rpmsg_channel *, u32, u32, void *, int, bool);
>   *
>   * Returns 0 on success and an appropriate error value on failure.
>   */
> -static inline int rpmsg_send(struct rpmsg_channel *rpdev, void *data, int
> len)
> +static inline int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int
> len)
>  {
> -	u32 src = rpdev->src, dst = rpdev->dst;
> +	struct rpmsg_channel *rpdev = ept->rpdev;
> +	u32 src = ept->addr, dst = rpdev->dst;
As this function is part of rpmsg API, it will be good to verify pointers before use.
> 
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
>  }
> 
>  /**
>   * rpmsg_sendto() - send a message across to the remote processor, specify
> dst
> - * @rpdev: the rpmsg channel
> + * @ept: the rpmsg endpoint
>   * @data: payload of message
>   * @len: length of payload
>   * @dst: destination address
>   *
>   * This function sends @data of length @len to the remote @dst address.
> - * The message will be sent to the remote processor which the @rpdev
> - * channel belongs to, using @rpdev's source address.
> + * The message will be sent to the remote processor which the @ept
> + * endpoint belongs to, using @ept's address as source.
>   * In case there are no TX buffers available, the function will block until
>   * one becomes available, or a timeout of 15 seconds elapses. When the
> latter
>   * happens, -ERESTARTSYS is returned.
> @@ -234,16 +236,17 @@ static inline int rpmsg_send(struct rpmsg_channel
> *rpdev, void *data, int len)
>   * Returns 0 on success and an appropriate error value on failure.
>   */
>  static inline
> -int rpmsg_sendto(struct rpmsg_channel *rpdev, void *data, int len, u32 dst)
> +int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
>  {
> -	u32 src = rpdev->src;
> +	struct rpmsg_channel *rpdev = ept->rpdev;
> +	u32 src = ept->addr;
ditto

> 
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
>  }
> 
>  /**
>   * rpmsg_send_offchannel() - send a message using explicit src/dst
> addresses
> - * @rpdev: the rpmsg channel
> + * @ept: the rpmsg endpoint
>   * @src: source address
>   * @dst: destination address
>   * @data: payload of message
> @@ -251,8 +254,8 @@ int rpmsg_sendto(struct rpmsg_channel *rpdev, void
> *data, int len, u32 dst)
>   *
>   * This function sends @data of length @len to the remote @dst address,
>   * and uses @src as the source address.
> - * The message will be sent to the remote processor which the @rpdev
> - * channel belongs to.
> + * The message will be sent to the remote processor which the @ept
> + * endpoint belongs to.
>   * In case there are no TX buffers available, the function will block until
>   * one becomes available, or a timeout of 15 seconds elapses. When the
> latter
>   * happens, -ERESTARTSYS is returned.
> @@ -262,21 +265,24 @@ int rpmsg_sendto(struct rpmsg_channel *rpdev,
> void *data, int len, u32 dst)
>   * Returns 0 on success and an appropriate error value on failure.
>   */
>  static inline
> -int rpmsg_send_offchannel(struct rpmsg_channel *rpdev, u32 src, u32 dst,
> +int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
>  			  void *data, int len)
>  {
> +	struct rpmsg_channel *rpdev = ept->rpdev;
ditto
> +
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
>  }
> 
>  /**
>   * rpmsg_send() - send a message across to the remote processor
Function name and description not aligned with code.
Should be rpmsg_trysend
May be in another patch...

> - * @rpdev: the rpmsg channel
> + * @ept: the rpmsg endpoint
>   * @data: payload of message
>   * @len: length of payload
>   *
> - * This function sends @data of length @len on the @rpdev channel.
> - * The message will be sent to the remote processor which the @rpdev
> - * channel belongs to, using @rpdev's source and destination addresses.
> + * This function sends @data of length @len on the @ept endpoint.
> + * The message will be sent to the remote processor which the @ept
> + * endpoint belongs to, using @ept's addres as source and its associated
> + * rpdev's address as destination.
>   * In case there are no TX buffers available, the function will immediately
>   * return -ENOMEM without waiting until one becomes available.
>   *
> @@ -285,23 +291,24 @@ int rpmsg_send_offchannel(struct rpmsg_channel
> *rpdev, u32 src, u32 dst,
>   * Returns 0 on success and an appropriate error value on failure.
>   */
>  static inline
> -int rpmsg_trysend(struct rpmsg_channel *rpdev, void *data, int len)
> +int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
>  {
> -	u32 src = rpdev->src, dst = rpdev->dst;
> +	struct rpmsg_channel *rpdev = ept->rpdev;
> +	u32 src = ept->addr, dst = rpdev->dst;
Pointer check before use
> 
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
>  }
> 
>  /**
>   * rpmsg_sendto() - send a message across to the remote processor, specify
> dst
Function name should be rpmsg_trysendto
> - * @rpdev: the rpmsg channel
> + * @ept: the rpmsg endpoint
>   * @data: payload of message
>   * @len: length of payload
>   * @dst: destination address
>   *
>   * This function sends @data of length @len to the remote @dst address.
> - * The message will be sent to the remote processor which the @rpdev
> - * channel belongs to, using @rpdev's source address.
> + * The message will be sent to the remote processor which the @ept
> + * endpoint belongs to, using @ept's address as source.
>   * In case there are no TX buffers available, the function will immediately
>   * return -ENOMEM without waiting until one becomes available.
>   *
> @@ -310,16 +317,17 @@ int rpmsg_trysend(struct rpmsg_channel *rpdev,
> void *data, int len)
>   * Returns 0 on success and an appropriate error value on failure.
>   */
>  static inline
> -int rpmsg_trysendto(struct rpmsg_channel *rpdev, void *data, int len, u32
> dst)
> +int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32
> dst)
>  {
> -	u32 src = rpdev->src;
> +	struct rpmsg_channel *rpdev = ept->rpdev;
> +	u32 src = ept->addr;
Check pointer before use
> 
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
>  }
> 
>  /**
>   * rpmsg_send_offchannel() - send a message using explicit src/dst
> addresses
Description for rpmsg_trysend_offchannel...

> - * @rpdev: the rpmsg channel
> + * @ept: the rpmsg endpoint
>   * @src: source address
>   * @dst: destination address
>   * @data: payload of message
> @@ -327,8 +335,8 @@ int rpmsg_trysendto(struct rpmsg_channel *rpdev,
> void *data, int len, u32 dst)
>   *
>   * This function sends @data of length @len to the remote @dst address,
>   * and uses @src as the source address.
> - * The message will be sent to the remote processor which the @rpdev
> - * channel belongs to.
> + * The message will be sent to the remote processor which the @ept
> + * endpoint belongs to.
>   * In case there are no TX buffers available, the function will immediately
>   * return -ENOMEM without waiting until one becomes available.
>   *
> @@ -337,9 +345,11 @@ int rpmsg_trysendto(struct rpmsg_channel *rpdev,
> void *data, int len, u32 dst)
>   * Returns 0 on success and an appropriate error value on failure.
>   */
>  static inline
> -int rpmsg_trysend_offchannel(struct rpmsg_channel *rpdev, u32 src, u32
> dst,
> +int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32
> dst,
>  			     void *data, int len)
>  {
> +	struct rpmsg_channel *rpdev = ept->rpdev;
> +
Point check before use
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
>  }

Regards,
Loic 

> 
> --
> 2.5.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-remoteproc" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 54+ messages in thread

* RE: [PATCH 08/14] rpmsg: Split rpmsg core and virtio backend
  2016-08-16  0:17   ` Bjorn Andersson
  (?)
@ 2016-08-18 11:59     ` Loic PALLARDY
  -1 siblings, 0 replies; 54+ messages in thread
From: Loic PALLARDY @ 2016-08-18 11:59 UTC (permalink / raw)
  To: Bjorn Andersson, Ohad Ben-Cohen
  Cc: linux-remoteproc, linux-arm-msm, linux-arm-kernel, linux-kernel,
	Sricharan R



> -----Original Message-----
> From: linux-remoteproc-owner@vger.kernel.org [mailto:linux-remoteproc-
> owner@vger.kernel.org] On Behalf Of Bjorn Andersson
> Sent: Tuesday, August 16, 2016 2:17 AM
> To: Ohad Ben-Cohen <ohad@wizery.com>; Bjorn Andersson
> <bjorn.andersson@linaro.org>
> Cc: linux-remoteproc@vger.kernel.org; linux-arm-msm@vger.kernel.org;
> linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org;
> Sricharan R <sricharan@codeaurora.org>
> Subject: [PATCH 08/14] rpmsg: Split rpmsg core and virtio backend
> 
> Extract the generic rpmsg core functionality from the virtio rpmsg
> implementation, splitting the implementation in a rpmsg core and a
> virtio backend.
> 
> Based on initial work by Sricharan R <sricharan@codeaurora.org>
> 
> Cc: Sricharan R <sricharan@codeaurora.org>
> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> ---
>  drivers/rpmsg/Kconfig            |   4 +
>  drivers/rpmsg/Makefile           |   3 +-
>  drivers/rpmsg/rpmsg_core.c       | 513
> +++++++++++++++++++++++++++++++++++++++
>  drivers/rpmsg/rpmsg_internal.h   |  45 ++++
>  drivers/rpmsg/virtio_rpmsg_bus.c | 477 +-----------------------------------
Hi Bjorn,

Could you please regenerate the patch with  option -M (of git formatpatch) to detect file renames.
It will provide better visibility of differences between virtio_rpmsg_bus.c and rpmsg_core.c.

>  5 files changed, 569 insertions(+), 473 deletions(-)
>  create mode 100644 drivers/rpmsg/rpmsg_core.c
>  create mode 100644 drivers/rpmsg/rpmsg_internal.h
> 
> diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig
> index 69a219387582..40614be88c97 100644
> --- a/drivers/rpmsg/Kconfig
> +++ b/drivers/rpmsg/Kconfig
> @@ -3,6 +3,10 @@ menu "Rpmsg drivers"
>  # RPMSG always gets selected by whoever wants it
>  config RPMSG
>  	tristate
> +
> +config RPMSG_VIRTIO
> +	tristate
> +	select RPMSG
>  	select VIRTIO
>  	select VIRTUALIZATION
> 
Remoteproc Kconfig should be changed too to select RPMSG_VIRTIO instead of RPMSG.

Regards,
Loic

> diff --git a/drivers/rpmsg/Makefile b/drivers/rpmsg/Makefile
> index 7617fcb8259f..383213417a00 100644
> --- a/drivers/rpmsg/Makefile
> +++ b/drivers/rpmsg/Makefile
> @@ -1 +1,2 @@
> -obj-$(CONFIG_RPMSG)	+= virtio_rpmsg_bus.o
> +obj-$(CONFIG_RPMSG)	+= rpmsg_core.o
> +obj-$(CONFIG_RPMSG_VIRTIO) += virtio_rpmsg_bus.o
> diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
> new file mode 100644
> index 000000000000..73bbc5ea5778
> --- /dev/null
> +++ b/drivers/rpmsg/rpmsg_core.c
> @@ -0,0 +1,513 @@
> +/*
> + * Virtio-based remote processor messaging bus
> + *
> + * Copyright (C) 2011 Texas Instruments, Inc.
> + * Copyright (C) 2011 Google, Inc.
> + *
> + * Ohad Ben-Cohen <ohad@wizery.com>
> + * Brian Swetland <swetland@google.com>
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#define pr_fmt(fmt) "%s: " fmt, __func__
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/virtio.h>
> +#include <linux/virtio_ids.h>
> +#include <linux/virtio_config.h>
> +#include <linux/scatterlist.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/slab.h>
> +#include <linux/idr.h>
> +#include <linux/jiffies.h>
> +#include <linux/sched.h>
> +#include <linux/wait.h>
> +#include <linux/rpmsg.h>
> +#include <linux/mutex.h>
> +#include <linux/of_device.h>
> +
> +#include "rpmsg_internal.h"
> +
> +/**
> + * rpmsg_create_ept() - create a new rpmsg_endpoint
> + * @rpdev: rpmsg channel device
> + * @cb: rx callback handler
> + * @priv: private data for the driver's use
> + * @addr: local rpmsg address to bind with @cb
> + *
> + * Every rpmsg address in the system is bound to an rx callback (so when
> + * inbound messages arrive, they are dispatched by the rpmsg bus using the
> + * appropriate callback handler) by means of an rpmsg_endpoint struct.
> + *
> + * This function allows drivers to create such an endpoint, and by that,
> + * bind a callback, and possibly some private data too, to an rpmsg address
> + * (either one that is known in advance, or one that will be dynamically
> + * assigned for them).
> + *
> + * Simple rpmsg drivers need not call rpmsg_create_ept, because an
> endpoint
> + * is already created for them when they are probed by the rpmsg bus
> + * (using the rx callback provided when they registered to the rpmsg bus).
> + *
> + * So things should just work for simple drivers: they already have an
> + * endpoint, their rx callback is bound to their rpmsg address, and when
> + * relevant inbound messages arrive (i.e. messages which their dst address
> + * equals to the src address of their rpmsg channel), the driver's handler
> + * is invoked to process it.
> + *
> + * That said, more complicated drivers might do need to allocate
> + * additional rpmsg addresses, and bind them to different rx callbacks.
> + * To accomplish that, those drivers need to call this function.
> + *
> + * Drivers should provide their @rpdev channel (so the new endpoint would
> belong
> + * to the same remote processor their channel belongs to), an rx callback
> + * function, an optional private data (which is provided back when the
> + * rx callback is invoked), and an address they want to bind with the
> + * callback. If @addr is RPMSG_ADDR_ANY, then rpmsg_create_ept will
> + * dynamically assign them an available rpmsg address (drivers should have
> + * a very good reason why not to always use RPMSG_ADDR_ANY here).
> + *
> + * Returns a pointer to the endpoint on success, or NULL on error.
> + */
> +struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev,
> +				rpmsg_rx_cb_t cb, void *priv, u32 addr)
> +{
> +	return rpdev->create_ept(rpdev, cb, priv, addr);
> +}
> +EXPORT_SYMBOL(rpmsg_create_ept);
> +
> +/**
> + * rpmsg_destroy_ept() - destroy an existing rpmsg endpoint
> + * @ept: endpoing to destroy
> + *
> + * Should be used by drivers to destroy an rpmsg endpoint previously
> + * created with rpmsg_create_ept().
> + */
> +void rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
> +{
> +	ept->rpdev->destroy_ept(ept);
> +}
> +EXPORT_SYMBOL(rpmsg_destroy_ept);
> +
> +/**
> + * rpmsg_send() - send a message across to the remote processor
> + * @ept: the rpmsg endpoint
> + * @data: payload of message
> + * @len: length of payload
> + *
> + * This function sends @data of length @len on the @ept endpoint.
> + * The message will be sent to the remote processor which the @ept
> + * endpoint belongs to, using @ept's address and its associated rpmsg
> + * device destination addresses.
> + * In case there are no TX buffers available, the function will block until
> + * one becomes available, or a timeout of 15 seconds elapses. When the
> latter
> + * happens, -ERESTARTSYS is returned.
> + *
> + * Can only be called from process context (for now).
> + *
> + * Returns 0 on success and an appropriate error value on failure.
> + */
> +int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
> +{
> +	struct rpmsg_device *rpdev = ept->rpdev;
> +
> +	return rpdev->send(ept, data, len);
> +}
> +
> +/**
> + * rpmsg_sendto() - send a message across to the remote processor,
> specify dst
> + * @ept: the rpmsg endpoint
> + * @data: payload of message
> + * @len: length of payload
> + * @dst: destination address
> + *
> + * This function sends @data of length @len to the remote @dst address.
> + * The message will be sent to the remote processor which the @ept
> + * endpoint belongs to, using @ept's address as source.
> + * In case there are no TX buffers available, the function will block until
> + * one becomes available, or a timeout of 15 seconds elapses. When the
> latter
> + * happens, -ERESTARTSYS is returned.
> + *
> + * Can only be called from process context (for now).
> + *
> + * Returns 0 on success and an appropriate error value on failure.
> + */
> +int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
> +{
> +	struct rpmsg_device *rpdev = ept->rpdev;
> +
> +	return rpdev->sendto(ept, data, len, dst);
> +}
> +EXPORT_SYMBOL(rpmsg_sendto);
> +
> +/**
> + * rpmsg_send_offchannel() - send a message using explicit src/dst
> addresses
> + * @ept: the rpmsg endpoint
> + * @src: source address
> + * @dst: destination address
> + * @data: payload of message
> + * @len: length of payload
> + *
> + * This function sends @data of length @len to the remote @dst address,
> + * and uses @src as the source address.
> + * The message will be sent to the remote processor which the @ept
> + * endpoint belongs to.
> + * In case there are no TX buffers available, the function will block until
> + * one becomes available, or a timeout of 15 seconds elapses. When the
> latter
> + * happens, -ERESTARTSYS is returned.
> + *
> + * Can only be called from process context (for now).
> + *
> + * Returns 0 on success and an appropriate error value on failure.
> + */
> +int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
> +			  void *data, int len)
> +{
> +	struct rpmsg_device *rpdev = ept->rpdev;
> +
> +	return rpdev->send_offchannel(ept, src, dst, data, len);
> +}
> +EXPORT_SYMBOL(rpmsg_send_offchannel);
> +
> +/**
> + * rpmsg_send() - send a message across to the remote processor
> + * @ept: the rpmsg endpoint
> + * @data: payload of message
> + * @len: length of payload
> + *
> + * This function sends @data of length @len on the @ept endpoint.
> + * The message will be sent to the remote processor which the @ept
> + * endpoint belongs to, using @ept's address as source and its associated
> + * rpdev's address as destination.
> + * In case there are no TX buffers available, the function will immediately
> + * return -ENOMEM without waiting until one becomes available.
> + *
> + * Can only be called from process context (for now).
> + *
> + * Returns 0 on success and an appropriate error value on failure.
> + */
> +int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
> +{
> +	struct rpmsg_device *rpdev = ept->rpdev;
> +
> +	return rpdev->trysend(ept, data, len);
> +}
> +EXPORT_SYMBOL(rpmsg_trysend);
> +
> +/**
> + * rpmsg_sendto() - send a message across to the remote processor,
> specify dst
> + * @ept: the rpmsg endpoint
> + * @data: payload of message
> + * @len: length of payload
> + * @dst: destination address
> + *
> + * This function sends @data of length @len to the remote @dst address.
> + * The message will be sent to the remote processor which the @ept
> + * endpoint belongs to, using @ept's address as source.
> + * In case there are no TX buffers available, the function will immediately
> + * return -ENOMEM without waiting until one becomes available.
> + *
> + * Can only be called from process context (for now).
> + *
> + * Returns 0 on success and an appropriate error value on failure.
> + */
> +int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32
> dst)
> +{
> +	struct rpmsg_device *rpdev = ept->rpdev;
> +
> +	return rpdev->trysendto(ept, data, len, dst);
> +}
> +EXPORT_SYMBOL(rpmsg_trysendto);
> +
> +/**
> + * rpmsg_send_offchannel() - send a message using explicit src/dst
> addresses
> + * @ept: the rpmsg endpoint
> + * @src: source address
> + * @dst: destination address
> + * @data: payload of message
> + * @len: length of payload
> + *
> + * This function sends @data of length @len to the remote @dst address,
> + * and uses @src as the source address.
> + * The message will be sent to the remote processor which the @ept
> + * endpoint belongs to.
> + * In case there are no TX buffers available, the function will immediately
> + * return -ENOMEM without waiting until one becomes available.
> + *
> + * Can only be called from process context (for now).
> + *
> + * Returns 0 on success and an appropriate error value on failure.
> + */
> +int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32
> dst,
> +			     void *data, int len)
> +{
> +	struct rpmsg_device *rpdev = ept->rpdev;
> +
> +	return rpdev->trysend_offchannel(ept, src, dst, data, len);
> +}
> +EXPORT_SYMBOL(rpmsg_trysend_offchannel);
> +
> +/* sysfs show configuration fields */
> +#define rpmsg_show_attr(field, path, format_string)			\
> +static ssize_t								\
> +field##_show(struct device *dev,					\
> +			struct device_attribute *attr, char *buf)	\
> +{									\
> +	struct rpmsg_device *rpdev = to_rpmsg_device(dev);		\
> +									\
> +	return sprintf(buf, format_string, rpdev->path);		\
> +}
> +
> +/* for more info, see Documentation/ABI/testing/sysfs-bus-rpmsg */
> +rpmsg_show_attr(name, id.name, "%s\n");
> +rpmsg_show_attr(src, src, "0x%x\n");
> +rpmsg_show_attr(dst, dst, "0x%x\n");
> +rpmsg_show_attr(announce, announce ? "true" : "false", "%s\n");
> +
> +static ssize_t modalias_show(struct device *dev,
> +			     struct device_attribute *attr, char *buf)
> +{
> +	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> +
> +	return sprintf(buf, RPMSG_DEVICE_MODALIAS_FMT "\n", rpdev-
> >id.name);
> +}
> +
> +static struct device_attribute rpmsg_dev_attrs[] = {
> +	__ATTR_RO(name),
> +	__ATTR_RO(modalias),
> +	__ATTR_RO(dst),
> +	__ATTR_RO(src),
> +	__ATTR_RO(announce),
> +	__ATTR_NULL
> +};
> +
> +/* rpmsg devices and drivers are matched using the service name */
> +static inline int rpmsg_id_match(const struct rpmsg_device *rpdev,
> +				  const struct rpmsg_device_id *id)
> +{
> +	return strncmp(id->name, rpdev->id.name, RPMSG_NAME_SIZE) ==
> 0;
> +}
> +
> +/* match rpmsg channel and rpmsg driver */
> +static int rpmsg_dev_match(struct device *dev, struct device_driver *drv)
> +{
> +	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> +	struct rpmsg_driver *rpdrv = to_rpmsg_driver(drv);
> +	const struct rpmsg_device_id *ids = rpdrv->id_table;
> +	unsigned int i;
> +
> +	if (ids)
> +		for (i = 0; ids[i].name[0]; i++)
> +			if (rpmsg_id_match(rpdev, &ids[i]))
> +				return 1;
> +
> +	return of_driver_match_device(dev, drv);
> +}
> +
> +static int rpmsg_uevent(struct device *dev, struct kobj_uevent_env *env)
> +{
> +	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> +
> +	return add_uevent_var(env, "MODALIAS="
> RPMSG_DEVICE_MODALIAS_FMT,
> +					rpdev->id.name);
> +}
> +
> +/*
> + * when an rpmsg driver is probed with a channel, we seamlessly create
> + * it an endpoint, binding its rx callback to a unique local rpmsg
> + * address.
> + *
> + * if we need to, we also announce about this channel to the remote
> + * processor (needed in case the driver is exposing an rpmsg service).
> + */
> +static int rpmsg_dev_probe(struct device *dev)
> +{
> +	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> +	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
> +	struct rpmsg_endpoint *ept;
> +	int err;
> +
> +	ept = rpmsg_create_ept(rpdev, rpdrv->callback, NULL, rpdev->src);
> +	if (!ept) {
> +		dev_err(dev, "failed to create endpoint\n");
> +		err = -ENOMEM;
> +		goto out;
> +	}
> +
> +	rpdev->ept = ept;
> +	rpdev->src = ept->addr;
> +
> +	err = rpdrv->probe(rpdev);
> +	if (err) {
> +		dev_err(dev, "%s: failed: %d\n", __func__, err);
> +		rpmsg_destroy_ept(ept);
> +		goto out;
> +	}
> +
> +	if (rpdev->announce_create)
> +		err = rpdev->announce_create(rpdev);
> +out:
> +	return err;
> +}
> +
> +static int rpmsg_dev_remove(struct device *dev)
> +{
> +	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> +	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
> +	int err = 0;
> +
> +	if (rpdev->announce_destroy)
> +		err = rpdev->announce_destroy(rpdev);
> +
> +	rpdrv->remove(rpdev);
> +
> +	rpmsg_destroy_ept(rpdev->ept);
> +
> +	return err;
> +}
> +
> +static struct bus_type rpmsg_bus = {
> +	.name		= "rpmsg",
> +	.match		= rpmsg_dev_match,
> +	.dev_attrs	= rpmsg_dev_attrs,
> +	.uevent		= rpmsg_uevent,
> +	.probe		= rpmsg_dev_probe,
> +	.remove		= rpmsg_dev_remove,
> +};
> +
> +static void rpmsg_release_device(struct device *dev)
> +{
> +	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> +
> +	kfree(rpdev);
> +}
> +
> +int rpmsg_register_device(struct rpmsg_device *rpdev)
> +{
> +	struct device *dev = &rpdev->dev;
> +	int ret;
> +
> +	dev_set_name(&rpdev->dev, "%s:%s",
> +		     dev_name(dev->parent), rpdev->id.name);
> +
> +	rpdev->dev.bus = &rpmsg_bus;
> +	rpdev->dev.release = rpmsg_release_device;
> +
> +	ret = device_register(&rpdev->dev);
> +	if (ret) {
> +		dev_err(dev, "device_register failed: %d\n", ret);
> +		put_device(&rpdev->dev);
> +	}
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL(rpmsg_register_device);
> +
> +/*
> + * match an rpmsg channel with a channel info struct.
> + * this is used to make sure we're not creating rpmsg devices for channels
> + * that already exist.
> + */
> +static int rpmsg_channel_match(struct device *dev, void *data)
> +{
> +	struct rpmsg_channel_info *chinfo = data;
> +	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> +
> +	if (chinfo->src != RPMSG_ADDR_ANY && chinfo->src != rpdev->src)
> +		return 0;
> +
> +	if (chinfo->dst != RPMSG_ADDR_ANY && chinfo->dst != rpdev->dst)
> +		return 0;
> +
> +	if (strncmp(chinfo->name, rpdev->id.name, RPMSG_NAME_SIZE))
> +		return 0;
> +
> +	/* found a match ! */
> +	return 1;
> +}
> +
> +struct device *rpmsg_find_device(struct device *parent,
> +				 struct rpmsg_channel_info *chinfo)
> +{
> +	return device_find_child(parent, chinfo, rpmsg_channel_match);
> +
> +}
> +EXPORT_SYMBOL(rpmsg_find_device);
> +
> +/*
> + * find an existing channel using its name + address properties,
> + * and destroy it
> + */
> +int rpmsg_unregister_device(struct device *parent,
> +			    struct rpmsg_channel_info *chinfo)
> +{
> +	struct device *dev;
> +
> +	dev = rpmsg_find_device(parent, chinfo);
> +	if (!dev)
> +		return -EINVAL;
> +
> +	device_unregister(dev);
> +
> +	put_device(dev);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(rpmsg_unregister_device);
> +
> +/**
> + * __register_rpmsg_driver() - register an rpmsg driver with the rpmsg bus
> + * @rpdrv: pointer to a struct rpmsg_driver
> + * @owner: owning module/driver
> + *
> + * Returns 0 on success, and an appropriate error value on failure.
> + */
> +int __register_rpmsg_driver(struct rpmsg_driver *rpdrv, struct module
> *owner)
> +{
> +	rpdrv->drv.bus = &rpmsg_bus;
> +	rpdrv->drv.owner = owner;
> +	return driver_register(&rpdrv->drv);
> +}
> +EXPORT_SYMBOL(__register_rpmsg_driver);
> +
> +/**
> + * unregister_rpmsg_driver() - unregister an rpmsg driver from the rpmsg
> bus
> + * @rpdrv: pointer to a struct rpmsg_driver
> + *
> + * Returns 0 on success, and an appropriate error value on failure.
> + */
> +void unregister_rpmsg_driver(struct rpmsg_driver *rpdrv)
> +{
> +	driver_unregister(&rpdrv->drv);
> +}
> +EXPORT_SYMBOL(unregister_rpmsg_driver);
> +
> +
> +static int __init rpmsg_init(void)
> +{
> +	int ret;
> +
> +	ret = bus_register(&rpmsg_bus);
> +	if (ret)
> +		pr_err("failed to register rpmsg bus: %d\n", ret);
> +
> +	return ret;
> +}
> +postcore_initcall(rpmsg_init);
> +
> +static void __exit rpmsg_fini(void)
> +{
> +	bus_unregister(&rpmsg_bus);
> +}
> +module_exit(rpmsg_fini);
> +
> +MODULE_DESCRIPTION("remote processor messaging bus");
> +MODULE_LICENSE("GPL v2");
> diff --git a/drivers/rpmsg/rpmsg_internal.h
> b/drivers/rpmsg/rpmsg_internal.h
> new file mode 100644
> index 000000000000..fa91075c7956
> --- /dev/null
> +++ b/drivers/rpmsg/rpmsg_internal.h
> @@ -0,0 +1,45 @@
> +/*
> + * Virtio-based remote processor messaging bus
> + *
> + * Copyright (C) 2011 Texas Instruments, Inc.
> + * Copyright (C) 2011 Google, Inc.
> + *
> + * Ohad Ben-Cohen <ohad@wizery.com>
> + * Brian Swetland <swetland@google.com>
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __RPMSG_INTERNAL_H__
> +#define __RPMSG_INTERNAL_H__
> +
> +#define to_rpmsg_device(d) container_of(d, struct rpmsg_device, dev)
> +#define to_rpmsg_driver(d) container_of(d, struct rpmsg_driver, drv)
> +
> +/**
> + * struct rpmsg_channel_info - internal channel info representation
> + * @name: name of service
> + * @src: local address
> + * @dst: destination address
> + */
> +struct rpmsg_channel_info {
> +	char name[RPMSG_NAME_SIZE];
> +	u32 src;
> +	u32 dst;
> +};
> +
> +int rpmsg_register_device(struct rpmsg_device *rpdev);
> +int rpmsg_unregister_device(struct device *parent,
> +			    struct rpmsg_channel_info *chinfo);
> +
> +struct device *rpmsg_find_device(struct device *parent,
> +				 struct rpmsg_channel_info *chinfo);
> +
> +#endif
> diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c
> b/drivers/rpmsg/virtio_rpmsg_bus.c
> index 5cadb75a225d..779c54304774 100644
> --- a/drivers/rpmsg/virtio_rpmsg_bus.c
> +++ b/drivers/rpmsg/virtio_rpmsg_bus.c
> @@ -35,6 +35,8 @@
>  #include <linux/mutex.h>
>  #include <linux/of_device.h>
> 
> +#include "rpmsg_internal.h"
> +
>  /**
>   * struct virtproc_info - virtual remote processor state
>   * @vdev:	the virtio device
> @@ -73,21 +75,6 @@ struct virtproc_info {
>  	struct rpmsg_endpoint *ns_ept;
>  };
> 
> -/**
> - * struct rpmsg_channel_info - internal channel info representation
> - * @name: name of service
> - * @src: local address
> - * @dst: destination address
> - */
> -struct rpmsg_channel_info {
> -	char name[RPMSG_NAME_SIZE];
> -	u32 src;
> -	u32 dst;
> -};
> -
> -#define to_rpmsg_device(d) container_of(d, struct rpmsg_device, dev)
> -#define to_rpmsg_driver(d) container_of(d, struct rpmsg_driver, drv)
> -
>  /*
>   * We're allocating buffers of 512 bytes each for communications. The
>   * number of buffers will be computed from the number of buffers
> supported
> @@ -129,72 +116,6 @@ static int virtio_rpmsg_trysendto(struct
> rpmsg_endpoint *ept, void *data,
>  				  int len, u32 dst);
>  static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32
> src,
>  					   u32 dst, void *data, int len);
> -static int rpmsg_register_device(struct rpmsg_device *rpdev);
> -
> -/* sysfs show configuration fields */
> -#define rpmsg_show_attr(field, path, format_string)			\
> -static ssize_t								\
> -field##_show(struct device *dev,					\
> -			struct device_attribute *attr, char *buf)	\
> -{									\
> -	struct rpmsg_device *rpdev = to_rpmsg_device(dev);		\
> -									\
> -	return sprintf(buf, format_string, rpdev->path);		\
> -}
> -
> -/* for more info, see Documentation/ABI/testing/sysfs-bus-rpmsg */
> -rpmsg_show_attr(name, id.name, "%s\n");
> -rpmsg_show_attr(src, src, "0x%x\n");
> -rpmsg_show_attr(dst, dst, "0x%x\n");
> -rpmsg_show_attr(announce, announce ? "true" : "false", "%s\n");
> -
> -static ssize_t modalias_show(struct device *dev,
> -			     struct device_attribute *attr, char *buf)
> -{
> -	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> -
> -	return sprintf(buf, RPMSG_DEVICE_MODALIAS_FMT "\n", rpdev-
> >id.name);
> -}
> -
> -static struct device_attribute rpmsg_dev_attrs[] = {
> -	__ATTR_RO(name),
> -	__ATTR_RO(modalias),
> -	__ATTR_RO(dst),
> -	__ATTR_RO(src),
> -	__ATTR_RO(announce),
> -	__ATTR_NULL
> -};
> -
> -/* rpmsg devices and drivers are matched using the service name */
> -static inline int rpmsg_id_match(const struct rpmsg_device *rpdev,
> -				 const struct rpmsg_device_id *id)
> -{
> -	return strncmp(id->name, rpdev->id.name, RPMSG_NAME_SIZE) ==
> 0;
> -}
> -
> -/* match rpmsg channel and rpmsg driver */
> -static int rpmsg_dev_match(struct device *dev, struct device_driver *drv)
> -{
> -	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> -	struct rpmsg_driver *rpdrv = to_rpmsg_driver(drv);
> -	const struct rpmsg_device_id *ids = rpdrv->id_table;
> -	unsigned int i;
> -
> -	if (ids)
> -		for (i = 0; ids[i].name[0]; i++)
> -			if (rpmsg_id_match(rpdev, &ids[i]))
> -				return 1;
> -
> -	return of_driver_match_device(dev, drv);
> -}
> -
> -static int rpmsg_uevent(struct device *dev, struct kobj_uevent_env *env)
> -{
> -	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> -
> -	return add_uevent_var(env, "MODALIAS="
> RPMSG_DEVICE_MODALIAS_FMT,
> -					rpdev->id.name);
> -}
> 
>  /**
>   * __ept_release() - deallocate an rpmsg endpoint
> @@ -266,53 +187,6 @@ free_ept:
>  	return NULL;
>  }
> 
> -/**
> - * rpmsg_create_ept() - create a new rpmsg_endpoint
> - * @rpdev: rpmsg channel device
> - * @cb: rx callback handler
> - * @priv: private data for the driver's use
> - * @addr: local rpmsg address to bind with @cb
> - *
> - * Every rpmsg address in the system is bound to an rx callback (so when
> - * inbound messages arrive, they are dispatched by the rpmsg bus using the
> - * appropriate callback handler) by means of an rpmsg_endpoint struct.
> - *
> - * This function allows drivers to create such an endpoint, and by that,
> - * bind a callback, and possibly some private data too, to an rpmsg address
> - * (either one that is known in advance, or one that will be dynamically
> - * assigned for them).
> - *
> - * Simple rpmsg drivers need not call rpmsg_create_ept, because an
> endpoint
> - * is already created for them when they are probed by the rpmsg bus
> - * (using the rx callback provided when they registered to the rpmsg bus).
> - *
> - * So things should just work for simple drivers: they already have an
> - * endpoint, their rx callback is bound to their rpmsg address, and when
> - * relevant inbound messages arrive (i.e. messages which their dst address
> - * equals to the src address of their rpmsg channel), the driver's handler
> - * is invoked to process it.
> - *
> - * That said, more complicated drivers might do need to allocate
> - * additional rpmsg addresses, and bind them to different rx callbacks.
> - * To accomplish that, those drivers need to call this function.
> - *
> - * Drivers should provide their @rpdev channel (so the new endpoint would
> belong
> - * to the same remote processor their channel belongs to), an rx callback
> - * function, an optional private data (which is provided back when the
> - * rx callback is invoked), and an address they want to bind with the
> - * callback. If @addr is RPMSG_ADDR_ANY, then rpmsg_create_ept will
> - * dynamically assign them an available rpmsg address (drivers should have
> - * a very good reason why not to always use RPMSG_ADDR_ANY here).
> - *
> - * Returns a pointer to the endpoint on success, or NULL on error.
> - */
> -struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev,
> -					rpmsg_rx_cb_t cb, void *priv, u32
> addr)
> -{
> -	return rpdev->create_ept(rpdev, cb, priv, addr);
> -}
> -EXPORT_SYMBOL(rpmsg_create_ept);
> -
>  static struct rpmsg_endpoint *virtio_rpmsg_create_ept(struct
> rpmsg_device *rpdev,
>  						      rpmsg_rx_cb_t cb,
>  						      void *priv, u32 addr)
> @@ -346,62 +220,11 @@ __rpmsg_destroy_ept(struct virtproc_info *vrp,
> struct rpmsg_endpoint *ept)
>  	kref_put(&ept->refcount, __ept_release);
>  }
> 
> -/**
> - * rpmsg_destroy_ept() - destroy an existing rpmsg endpoint
> - * @ept: endpoing to destroy
> - *
> - * Should be used by drivers to destroy an rpmsg endpoint previously
> - * created with rpmsg_create_ept().
> - */
> -void rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
> -{
> -	ept->rpdev->destroy_ept(ept);
> -}
> -EXPORT_SYMBOL(rpmsg_destroy_ept);
> -
>  static void virtio_rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
>  {
>  	__rpmsg_destroy_ept(ept->rpdev->vrp, ept);
>  }
> 
> -/*
> - * when an rpmsg driver is probed with a channel, we seamlessly create
> - * it an endpoint, binding its rx callback to a unique local rpmsg
> - * address.
> - *
> - * if we need to, we also announce about this channel to the remote
> - * processor (needed in case the driver is exposing an rpmsg service).
> - */
> -static int rpmsg_dev_probe(struct device *dev)
> -{
> -	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> -	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
> -	struct rpmsg_endpoint *ept;
> -	int err;
> -
> -	ept = rpmsg_create_ept(rpdev, rpdrv->callback, NULL, rpdev->src);
> -	if (!ept) {
> -		dev_err(dev, "failed to create endpoint\n");
> -		err = -ENOMEM;
> -		goto out;
> -	}
> -
> -	rpdev->ept = ept;
> -	rpdev->src = ept->addr;
> -
> -	err = rpdrv->probe(rpdev);
> -	if (err) {
> -		dev_err(dev, "%s: failed: %d\n", __func__, err);
> -		rpmsg_destroy_ept(ept);
> -		goto out;
> -	}
> -
> -	if (rpdev->announce_create)
> -		err = rpdev->announce_create(rpdev);
> -out:
> -	return err;
> -}
> -
>  static int virtio_rpmsg_announce_create(struct rpmsg_device *rpdev)
>  {
>  	struct virtproc_info *vrp = rpdev->vrp;
> @@ -448,88 +271,6 @@ static int virtio_rpmsg_announce_destroy(struct
> rpmsg_device *rpdev)
>  	return err;
>  }
> 
> -static int rpmsg_dev_remove(struct device *dev)
> -{
> -	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> -	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
> -	int err = 0;
> -
> -	if (rpdev->announce_destroy)
> -		err = rpdev->announce_destroy(rpdev);
> -
> -	rpdrv->remove(rpdev);
> -
> -	rpmsg_destroy_ept(rpdev->ept);
> -
> -	return err;
> -}
> -
> -static struct bus_type rpmsg_bus = {
> -	.name		= "rpmsg",
> -	.match		= rpmsg_dev_match,
> -	.dev_attrs	= rpmsg_dev_attrs,
> -	.uevent		= rpmsg_uevent,
> -	.probe		= rpmsg_dev_probe,
> -	.remove		= rpmsg_dev_remove,
> -};
> -
> -/**
> - * __register_rpmsg_driver() - register an rpmsg driver with the rpmsg bus
> - * @rpdrv: pointer to a struct rpmsg_driver
> - * @owner: owning module/driver
> - *
> - * Returns 0 on success, and an appropriate error value on failure.
> - */
> -int __register_rpmsg_driver(struct rpmsg_driver *rpdrv, struct module
> *owner)
> -{
> -	rpdrv->drv.bus = &rpmsg_bus;
> -	rpdrv->drv.owner = owner;
> -	return driver_register(&rpdrv->drv);
> -}
> -EXPORT_SYMBOL(__register_rpmsg_driver);
> -
> -/**
> - * unregister_rpmsg_driver() - unregister an rpmsg driver from the rpmsg
> bus
> - * @rpdrv: pointer to a struct rpmsg_driver
> - *
> - * Returns 0 on success, and an appropriate error value on failure.
> - */
> -void unregister_rpmsg_driver(struct rpmsg_driver *rpdrv)
> -{
> -	driver_unregister(&rpdrv->drv);
> -}
> -EXPORT_SYMBOL(unregister_rpmsg_driver);
> -
> -static void rpmsg_release_device(struct device *dev)
> -{
> -	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> -
> -	kfree(rpdev);
> -}
> -
> -/*
> - * match an rpmsg channel with a channel info struct.
> - * this is used to make sure we're not creating rpmsg devices for channels
> - * that already exist.
> - */
> -static int rpmsg_device_match(struct device *dev, void *data)
> -{
> -	struct rpmsg_channel_info *chinfo = data;
> -	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> -
> -	if (chinfo->src != RPMSG_ADDR_ANY && chinfo->src != rpdev->src)
> -		return 0;
> -
> -	if (chinfo->dst != RPMSG_ADDR_ANY && chinfo->dst != rpdev->dst)
> -		return 0;
> -
> -	if (strncmp(chinfo->name, rpdev->id.name, RPMSG_NAME_SIZE))
> -		return 0;
> -
> -	/* found a match ! */
> -	return 1;
> -}
> -
>  static const struct rpmsg_device virtio_rpmsg_ops = {
>  	.create_ept = virtio_rpmsg_create_ept,
>  	.destroy_ept = virtio_rpmsg_destroy_ept,
> @@ -556,7 +297,7 @@ static struct rpmsg_device
> *rpmsg_create_channel(struct virtproc_info *vrp,
>  	int ret;
> 
>  	/* make sure a similar channel doesn't already exist */
> -	tmp = device_find_child(dev, chinfo, rpmsg_device_match);
> +	tmp = rpmsg_find_device(dev, chinfo);
>  	if (tmp) {
>  		/* decrement the matched device's refcount back */
>  		put_device(tmp);
> @@ -592,47 +333,6 @@ static struct rpmsg_device
> *rpmsg_create_channel(struct virtproc_info *vrp,
>  	return rpdev;
>  }
> 
> -static int rpmsg_register_device(struct rpmsg_device *rpdev)
> -{
> -	struct device *dev = &rpdev->dev;
> -	int ret;
> -
> -	dev_set_name(&rpdev->dev, "%s:%s",
> -		     dev_name(dev->parent), rpdev->id.name);
> -
> -	rpdev->dev.bus = &rpmsg_bus;
> -	rpdev->dev.release = rpmsg_release_device;
> -
> -	ret = device_register(&rpdev->dev);
> -	if (ret) {
> -		dev_err(dev, "device_register failed: %d\n", ret);
> -		put_device(&rpdev->dev);
> -	}
> -
> -	return ret;
> -}
> -
> -/*
> - * find an existing channel using its name + address properties,
> - * and destroy it
> - */
> -static int rpmsg_destroy_channel(struct virtproc_info *vrp,
> -				 struct rpmsg_channel_info *chinfo)
> -{
> -	struct virtio_device *vdev = vrp->vdev;
> -	struct device *dev;
> -
> -	dev = device_find_child(&vdev->dev, chinfo, rpmsg_device_match);
> -	if (!dev)
> -		return -EINVAL;
> -
> -	device_unregister(dev);
> -
> -	put_device(dev);
> -
> -	return 0;
> -}
> -
>  /* super simple buffer "allocator" that is just enough for now */
>  static void *get_a_tx_buf(struct virtproc_info *vrp)
>  {
> @@ -844,31 +544,6 @@ out:
>  	return err;
>  }
> 
> -/**
> - * rpmsg_send() - send a message across to the remote processor
> - * @ept: the rpmsg endpoint
> - * @data: payload of message
> - * @len: length of payload
> - *
> - * This function sends @data of length @len on the @ept endpoint.
> - * The message will be sent to the remote processor which the @ept
> - * endpoint belongs to, using @ept's address and its associated rpmsg
> - * device destination addresses.
> - * In case there are no TX buffers available, the function will block until
> - * one becomes available, or a timeout of 15 seconds elapses. When the
> latter
> - * happens, -ERESTARTSYS is returned.
> - *
> - * Can only be called from process context (for now).
> - *
> - * Returns 0 on success and an appropriate error value on failure.
> - */
> -int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
> -{
> -	struct rpmsg_device *rpdev = ept->rpdev;
> -
> -	return rpdev->send(ept, data, len);
> -}
> -
>  static int virtio_rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
>  {
>  	struct rpmsg_device *rpdev = ept->rpdev;
> @@ -877,32 +552,6 @@ static int virtio_rpmsg_send(struct rpmsg_endpoint
> *ept, void *data, int len)
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
>  }
> 
> -/**
> - * rpmsg_sendto() - send a message across to the remote processor, specify
> dst
> - * @ept: the rpmsg endpoint
> - * @data: payload of message
> - * @len: length of payload
> - * @dst: destination address
> - *
> - * This function sends @data of length @len to the remote @dst address.
> - * The message will be sent to the remote processor which the @ept
> - * endpoint belongs to, using @ept's address as source.
> - * In case there are no TX buffers available, the function will block until
> - * one becomes available, or a timeout of 15 seconds elapses. When the
> latter
> - * happens, -ERESTARTSYS is returned.
> - *
> - * Can only be called from process context (for now).
> - *
> - * Returns 0 on success and an appropriate error value on failure.
> - */
> -int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
> -{
> -	struct rpmsg_device *rpdev = ept->rpdev;
> -
> -	return rpdev->sendto(ept, data, len, dst);
> -}
> -EXPORT_SYMBOL(rpmsg_sendto);
> -
>  static int virtio_rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int
> len,
>  			       u32 dst)
>  {
> @@ -912,35 +561,6 @@ static int virtio_rpmsg_sendto(struct
> rpmsg_endpoint *ept, void *data, int len,
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
>  }
> 
> -/**
> - * rpmsg_send_offchannel() - send a message using explicit src/dst
> addresses
> - * @ept: the rpmsg endpoint
> - * @src: source address
> - * @dst: destination address
> - * @data: payload of message
> - * @len: length of payload
> - *
> - * This function sends @data of length @len to the remote @dst address,
> - * and uses @src as the source address.
> - * The message will be sent to the remote processor which the @ept
> - * endpoint belongs to.
> - * In case there are no TX buffers available, the function will block until
> - * one becomes available, or a timeout of 15 seconds elapses. When the
> latter
> - * happens, -ERESTARTSYS is returned.
> - *
> - * Can only be called from process context (for now).
> - *
> - * Returns 0 on success and an appropriate error value on failure.
> - */
> -int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
> -			  void *data, int len)
> -{
> -	struct rpmsg_device *rpdev = ept->rpdev;
> -
> -	return rpdev->send_offchannel(ept, src, dst, data, len);
> -}
> -EXPORT_SYMBOL(rpmsg_send_offchannel);
> -
>  static int virtio_rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32
> src,
>  					u32 dst, void *data, int len)
>  {
> @@ -949,31 +569,6 @@ static int virtio_rpmsg_send_offchannel(struct
> rpmsg_endpoint *ept, u32 src,
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
>  }
> 
> -/**
> - * rpmsg_send() - send a message across to the remote processor
> - * @ept: the rpmsg endpoint
> - * @data: payload of message
> - * @len: length of payload
> - *
> - * This function sends @data of length @len on the @ept endpoint.
> - * The message will be sent to the remote processor which the @ept
> - * endpoint belongs to, using @ept's addres as source and its associated
> - * rpdev's address as destination.
> - * In case there are no TX buffers available, the function will immediately
> - * return -ENOMEM without waiting until one becomes available.
> - *
> - * Can only be called from process context (for now).
> - *
> - * Returns 0 on success and an appropriate error value on failure.
> - */
> -int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
> -{
> -	struct rpmsg_device *rpdev = ept->rpdev;
> -
> -	return rpdev->trysend(ept, data, len);
> -}
> -EXPORT_SYMBOL(rpmsg_trysend);
> -
>  static int virtio_rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int
> len)
>  {
>  	struct rpmsg_device *rpdev = ept->rpdev;
> @@ -982,31 +577,6 @@ static int virtio_rpmsg_trysend(struct
> rpmsg_endpoint *ept, void *data, int len)
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
>  }
> 
> -/**
> - * rpmsg_sendto() - send a message across to the remote processor, specify
> dst
> - * @ept: the rpmsg endpoint
> - * @data: payload of message
> - * @len: length of payload
> - * @dst: destination address
> - *
> - * This function sends @data of length @len to the remote @dst address.
> - * The message will be sent to the remote processor which the @ept
> - * endpoint belongs to, using @ept's address as source.
> - * In case there are no TX buffers available, the function will immediately
> - * return -ENOMEM without waiting until one becomes available.
> - *
> - * Can only be called from process context (for now).
> - *
> - * Returns 0 on success and an appropriate error value on failure.
> - */
> -int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32
> dst)
> -{
> -	struct rpmsg_device *rpdev = ept->rpdev;
> -
> -	return rpdev->trysendto(ept, data, len, dst);
> -}
> -EXPORT_SYMBOL(rpmsg_trysendto);
> -
>  static int virtio_rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data,
>  				  int len, u32 dst)
>  {
> @@ -1016,34 +586,6 @@ static int virtio_rpmsg_trysendto(struct
> rpmsg_endpoint *ept, void *data,
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
>  }
> 
> -/**
> - * rpmsg_send_offchannel() - send a message using explicit src/dst
> addresses
> - * @ept: the rpmsg endpoint
> - * @src: source address
> - * @dst: destination address
> - * @data: payload of message
> - * @len: length of payload
> - *
> - * This function sends @data of length @len to the remote @dst address,
> - * and uses @src as the source address.
> - * The message will be sent to the remote processor which the @ept
> - * endpoint belongs to.
> - * In case there are no TX buffers available, the function will immediately
> - * return -ENOMEM without waiting until one becomes available.
> - *
> - * Can only be called from process context (for now).
> - *
> - * Returns 0 on success and an appropriate error value on failure.
> - */
> -int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32
> dst,
> -			     void *data, int len)
> -{
> -	struct rpmsg_device *rpdev = ept->rpdev;
> -
> -	return rpdev->trysend_offchannel(ept, src, dst, data, len);
> -}
> -EXPORT_SYMBOL(rpmsg_trysend_offchannel);
> -
>  static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32
> src,
>  					   u32 dst, void *data, int len)
>  {
> @@ -1208,7 +750,7 @@ static void rpmsg_ns_cb(struct rpmsg_device
> *rpdev, void *data, int len,
>  	chinfo.dst = msg->addr;
> 
>  	if (msg->flags & RPMSG_NS_DESTROY) {
> -		ret = rpmsg_destroy_channel(vrp, &chinfo);
> +		ret = rpmsg_unregister_device(&vrp->vdev->dev, &chinfo);
>  		if (ret)
>  			dev_err(dev, "rpmsg_destroy_channel failed: %d\n",
> ret);
>  	} else {
> @@ -1393,17 +935,9 @@ static int __init rpmsg_init(void)
>  {
>  	int ret;
> 
> -	ret = bus_register(&rpmsg_bus);
> -	if (ret) {
> -		pr_err("failed to register rpmsg bus: %d\n", ret);
> -		return ret;
> -	}
> -
>  	ret = register_virtio_driver(&virtio_ipc_driver);
> -	if (ret) {
> +	if (ret)
>  		pr_err("failed to register virtio driver: %d\n", ret);
> -		bus_unregister(&rpmsg_bus);
> -	}
> 
>  	return ret;
>  }
> @@ -1412,7 +946,6 @@ subsys_initcall(rpmsg_init);
>  static void __exit rpmsg_fini(void)
>  {
>  	unregister_virtio_driver(&virtio_ipc_driver);
> -	bus_unregister(&rpmsg_bus);
>  }
>  module_exit(rpmsg_fini);
> 
> --
> 2.5.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-remoteproc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 54+ messages in thread

* RE: [PATCH 08/14] rpmsg: Split rpmsg core and virtio backend
@ 2016-08-18 11:59     ` Loic PALLARDY
  0 siblings, 0 replies; 54+ messages in thread
From: Loic PALLARDY @ 2016-08-18 11:59 UTC (permalink / raw)
  To: Bjorn Andersson, Ohad Ben-Cohen
  Cc: linux-remoteproc, linux-arm-msm, linux-arm-kernel, linux-kernel,
	Sricharan R



> -----Original Message-----
> From: linux-remoteproc-owner@vger.kernel.org [mailto:linux-remoteproc-
> owner@vger.kernel.org] On Behalf Of Bjorn Andersson
> Sent: Tuesday, August 16, 2016 2:17 AM
> To: Ohad Ben-Cohen <ohad@wizery.com>; Bjorn Andersson
> <bjorn.andersson@linaro.org>
> Cc: linux-remoteproc@vger.kernel.org; linux-arm-msm@vger.kernel.org;
> linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org;
> Sricharan R <sricharan@codeaurora.org>
> Subject: [PATCH 08/14] rpmsg: Split rpmsg core and virtio backend
> 
> Extract the generic rpmsg core functionality from the virtio rpmsg
> implementation, splitting the implementation in a rpmsg core and a
> virtio backend.
> 
> Based on initial work by Sricharan R <sricharan@codeaurora.org>
> 
> Cc: Sricharan R <sricharan@codeaurora.org>
> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> ---
>  drivers/rpmsg/Kconfig            |   4 +
>  drivers/rpmsg/Makefile           |   3 +-
>  drivers/rpmsg/rpmsg_core.c       | 513
> +++++++++++++++++++++++++++++++++++++++
>  drivers/rpmsg/rpmsg_internal.h   |  45 ++++
>  drivers/rpmsg/virtio_rpmsg_bus.c | 477 +-----------------------------------
Hi Bjorn,

Could you please regenerate the patch with  option -M (of git formatpatch) to detect file renames.
It will provide better visibility of differences between virtio_rpmsg_bus.c and rpmsg_core.c.

>  5 files changed, 569 insertions(+), 473 deletions(-)
>  create mode 100644 drivers/rpmsg/rpmsg_core.c
>  create mode 100644 drivers/rpmsg/rpmsg_internal.h
> 
> diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig
> index 69a219387582..40614be88c97 100644
> --- a/drivers/rpmsg/Kconfig
> +++ b/drivers/rpmsg/Kconfig
> @@ -3,6 +3,10 @@ menu "Rpmsg drivers"
>  # RPMSG always gets selected by whoever wants it
>  config RPMSG
>  	tristate
> +
> +config RPMSG_VIRTIO
> +	tristate
> +	select RPMSG
>  	select VIRTIO
>  	select VIRTUALIZATION
> 
Remoteproc Kconfig should be changed too to select RPMSG_VIRTIO instead of RPMSG.

Regards,
Loic

> diff --git a/drivers/rpmsg/Makefile b/drivers/rpmsg/Makefile
> index 7617fcb8259f..383213417a00 100644
> --- a/drivers/rpmsg/Makefile
> +++ b/drivers/rpmsg/Makefile
> @@ -1 +1,2 @@
> -obj-$(CONFIG_RPMSG)	+= virtio_rpmsg_bus.o
> +obj-$(CONFIG_RPMSG)	+= rpmsg_core.o
> +obj-$(CONFIG_RPMSG_VIRTIO) += virtio_rpmsg_bus.o
> diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
> new file mode 100644
> index 000000000000..73bbc5ea5778
> --- /dev/null
> +++ b/drivers/rpmsg/rpmsg_core.c
> @@ -0,0 +1,513 @@
> +/*
> + * Virtio-based remote processor messaging bus
> + *
> + * Copyright (C) 2011 Texas Instruments, Inc.
> + * Copyright (C) 2011 Google, Inc.
> + *
> + * Ohad Ben-Cohen <ohad@wizery.com>
> + * Brian Swetland <swetland@google.com>
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#define pr_fmt(fmt) "%s: " fmt, __func__
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/virtio.h>
> +#include <linux/virtio_ids.h>
> +#include <linux/virtio_config.h>
> +#include <linux/scatterlist.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/slab.h>
> +#include <linux/idr.h>
> +#include <linux/jiffies.h>
> +#include <linux/sched.h>
> +#include <linux/wait.h>
> +#include <linux/rpmsg.h>
> +#include <linux/mutex.h>
> +#include <linux/of_device.h>
> +
> +#include "rpmsg_internal.h"
> +
> +/**
> + * rpmsg_create_ept() - create a new rpmsg_endpoint
> + * @rpdev: rpmsg channel device
> + * @cb: rx callback handler
> + * @priv: private data for the driver's use
> + * @addr: local rpmsg address to bind with @cb
> + *
> + * Every rpmsg address in the system is bound to an rx callback (so when
> + * inbound messages arrive, they are dispatched by the rpmsg bus using the
> + * appropriate callback handler) by means of an rpmsg_endpoint struct.
> + *
> + * This function allows drivers to create such an endpoint, and by that,
> + * bind a callback, and possibly some private data too, to an rpmsg address
> + * (either one that is known in advance, or one that will be dynamically
> + * assigned for them).
> + *
> + * Simple rpmsg drivers need not call rpmsg_create_ept, because an
> endpoint
> + * is already created for them when they are probed by the rpmsg bus
> + * (using the rx callback provided when they registered to the rpmsg bus).
> + *
> + * So things should just work for simple drivers: they already have an
> + * endpoint, their rx callback is bound to their rpmsg address, and when
> + * relevant inbound messages arrive (i.e. messages which their dst address
> + * equals to the src address of their rpmsg channel), the driver's handler
> + * is invoked to process it.
> + *
> + * That said, more complicated drivers might do need to allocate
> + * additional rpmsg addresses, and bind them to different rx callbacks.
> + * To accomplish that, those drivers need to call this function.
> + *
> + * Drivers should provide their @rpdev channel (so the new endpoint would
> belong
> + * to the same remote processor their channel belongs to), an rx callback
> + * function, an optional private data (which is provided back when the
> + * rx callback is invoked), and an address they want to bind with the
> + * callback. If @addr is RPMSG_ADDR_ANY, then rpmsg_create_ept will
> + * dynamically assign them an available rpmsg address (drivers should have
> + * a very good reason why not to always use RPMSG_ADDR_ANY here).
> + *
> + * Returns a pointer to the endpoint on success, or NULL on error.
> + */
> +struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev,
> +				rpmsg_rx_cb_t cb, void *priv, u32 addr)
> +{
> +	return rpdev->create_ept(rpdev, cb, priv, addr);
> +}
> +EXPORT_SYMBOL(rpmsg_create_ept);
> +
> +/**
> + * rpmsg_destroy_ept() - destroy an existing rpmsg endpoint
> + * @ept: endpoing to destroy
> + *
> + * Should be used by drivers to destroy an rpmsg endpoint previously
> + * created with rpmsg_create_ept().
> + */
> +void rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
> +{
> +	ept->rpdev->destroy_ept(ept);
> +}
> +EXPORT_SYMBOL(rpmsg_destroy_ept);
> +
> +/**
> + * rpmsg_send() - send a message across to the remote processor
> + * @ept: the rpmsg endpoint
> + * @data: payload of message
> + * @len: length of payload
> + *
> + * This function sends @data of length @len on the @ept endpoint.
> + * The message will be sent to the remote processor which the @ept
> + * endpoint belongs to, using @ept's address and its associated rpmsg
> + * device destination addresses.
> + * In case there are no TX buffers available, the function will block until
> + * one becomes available, or a timeout of 15 seconds elapses. When the
> latter
> + * happens, -ERESTARTSYS is returned.
> + *
> + * Can only be called from process context (for now).
> + *
> + * Returns 0 on success and an appropriate error value on failure.
> + */
> +int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
> +{
> +	struct rpmsg_device *rpdev = ept->rpdev;
> +
> +	return rpdev->send(ept, data, len);
> +}
> +
> +/**
> + * rpmsg_sendto() - send a message across to the remote processor,
> specify dst
> + * @ept: the rpmsg endpoint
> + * @data: payload of message
> + * @len: length of payload
> + * @dst: destination address
> + *
> + * This function sends @data of length @len to the remote @dst address.
> + * The message will be sent to the remote processor which the @ept
> + * endpoint belongs to, using @ept's address as source.
> + * In case there are no TX buffers available, the function will block until
> + * one becomes available, or a timeout of 15 seconds elapses. When the
> latter
> + * happens, -ERESTARTSYS is returned.
> + *
> + * Can only be called from process context (for now).
> + *
> + * Returns 0 on success and an appropriate error value on failure.
> + */
> +int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
> +{
> +	struct rpmsg_device *rpdev = ept->rpdev;
> +
> +	return rpdev->sendto(ept, data, len, dst);
> +}
> +EXPORT_SYMBOL(rpmsg_sendto);
> +
> +/**
> + * rpmsg_send_offchannel() - send a message using explicit src/dst
> addresses
> + * @ept: the rpmsg endpoint
> + * @src: source address
> + * @dst: destination address
> + * @data: payload of message
> + * @len: length of payload
> + *
> + * This function sends @data of length @len to the remote @dst address,
> + * and uses @src as the source address.
> + * The message will be sent to the remote processor which the @ept
> + * endpoint belongs to.
> + * In case there are no TX buffers available, the function will block until
> + * one becomes available, or a timeout of 15 seconds elapses. When the
> latter
> + * happens, -ERESTARTSYS is returned.
> + *
> + * Can only be called from process context (for now).
> + *
> + * Returns 0 on success and an appropriate error value on failure.
> + */
> +int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
> +			  void *data, int len)
> +{
> +	struct rpmsg_device *rpdev = ept->rpdev;
> +
> +	return rpdev->send_offchannel(ept, src, dst, data, len);
> +}
> +EXPORT_SYMBOL(rpmsg_send_offchannel);
> +
> +/**
> + * rpmsg_send() - send a message across to the remote processor
> + * @ept: the rpmsg endpoint
> + * @data: payload of message
> + * @len: length of payload
> + *
> + * This function sends @data of length @len on the @ept endpoint.
> + * The message will be sent to the remote processor which the @ept
> + * endpoint belongs to, using @ept's address as source and its associated
> + * rpdev's address as destination.
> + * In case there are no TX buffers available, the function will immediately
> + * return -ENOMEM without waiting until one becomes available.
> + *
> + * Can only be called from process context (for now).
> + *
> + * Returns 0 on success and an appropriate error value on failure.
> + */
> +int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
> +{
> +	struct rpmsg_device *rpdev = ept->rpdev;
> +
> +	return rpdev->trysend(ept, data, len);
> +}
> +EXPORT_SYMBOL(rpmsg_trysend);
> +
> +/**
> + * rpmsg_sendto() - send a message across to the remote processor,
> specify dst
> + * @ept: the rpmsg endpoint
> + * @data: payload of message
> + * @len: length of payload
> + * @dst: destination address
> + *
> + * This function sends @data of length @len to the remote @dst address.
> + * The message will be sent to the remote processor which the @ept
> + * endpoint belongs to, using @ept's address as source.
> + * In case there are no TX buffers available, the function will immediately
> + * return -ENOMEM without waiting until one becomes available.
> + *
> + * Can only be called from process context (for now).
> + *
> + * Returns 0 on success and an appropriate error value on failure.
> + */
> +int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32
> dst)
> +{
> +	struct rpmsg_device *rpdev = ept->rpdev;
> +
> +	return rpdev->trysendto(ept, data, len, dst);
> +}
> +EXPORT_SYMBOL(rpmsg_trysendto);
> +
> +/**
> + * rpmsg_send_offchannel() - send a message using explicit src/dst
> addresses
> + * @ept: the rpmsg endpoint
> + * @src: source address
> + * @dst: destination address
> + * @data: payload of message
> + * @len: length of payload
> + *
> + * This function sends @data of length @len to the remote @dst address,
> + * and uses @src as the source address.
> + * The message will be sent to the remote processor which the @ept
> + * endpoint belongs to.
> + * In case there are no TX buffers available, the function will immediately
> + * return -ENOMEM without waiting until one becomes available.
> + *
> + * Can only be called from process context (for now).
> + *
> + * Returns 0 on success and an appropriate error value on failure.
> + */
> +int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32
> dst,
> +			     void *data, int len)
> +{
> +	struct rpmsg_device *rpdev = ept->rpdev;
> +
> +	return rpdev->trysend_offchannel(ept, src, dst, data, len);
> +}
> +EXPORT_SYMBOL(rpmsg_trysend_offchannel);
> +
> +/* sysfs show configuration fields */
> +#define rpmsg_show_attr(field, path, format_string)			\
> +static ssize_t								\
> +field##_show(struct device *dev,					\
> +			struct device_attribute *attr, char *buf)	\
> +{									\
> +	struct rpmsg_device *rpdev = to_rpmsg_device(dev);		\
> +									\
> +	return sprintf(buf, format_string, rpdev->path);		\
> +}
> +
> +/* for more info, see Documentation/ABI/testing/sysfs-bus-rpmsg */
> +rpmsg_show_attr(name, id.name, "%s\n");
> +rpmsg_show_attr(src, src, "0x%x\n");
> +rpmsg_show_attr(dst, dst, "0x%x\n");
> +rpmsg_show_attr(announce, announce ? "true" : "false", "%s\n");
> +
> +static ssize_t modalias_show(struct device *dev,
> +			     struct device_attribute *attr, char *buf)
> +{
> +	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> +
> +	return sprintf(buf, RPMSG_DEVICE_MODALIAS_FMT "\n", rpdev-
> >id.name);
> +}
> +
> +static struct device_attribute rpmsg_dev_attrs[] = {
> +	__ATTR_RO(name),
> +	__ATTR_RO(modalias),
> +	__ATTR_RO(dst),
> +	__ATTR_RO(src),
> +	__ATTR_RO(announce),
> +	__ATTR_NULL
> +};
> +
> +/* rpmsg devices and drivers are matched using the service name */
> +static inline int rpmsg_id_match(const struct rpmsg_device *rpdev,
> +				  const struct rpmsg_device_id *id)
> +{
> +	return strncmp(id->name, rpdev->id.name, RPMSG_NAME_SIZE) ==
> 0;
> +}
> +
> +/* match rpmsg channel and rpmsg driver */
> +static int rpmsg_dev_match(struct device *dev, struct device_driver *drv)
> +{
> +	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> +	struct rpmsg_driver *rpdrv = to_rpmsg_driver(drv);
> +	const struct rpmsg_device_id *ids = rpdrv->id_table;
> +	unsigned int i;
> +
> +	if (ids)
> +		for (i = 0; ids[i].name[0]; i++)
> +			if (rpmsg_id_match(rpdev, &ids[i]))
> +				return 1;
> +
> +	return of_driver_match_device(dev, drv);
> +}
> +
> +static int rpmsg_uevent(struct device *dev, struct kobj_uevent_env *env)
> +{
> +	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> +
> +	return add_uevent_var(env, "MODALIAS="
> RPMSG_DEVICE_MODALIAS_FMT,
> +					rpdev->id.name);
> +}
> +
> +/*
> + * when an rpmsg driver is probed with a channel, we seamlessly create
> + * it an endpoint, binding its rx callback to a unique local rpmsg
> + * address.
> + *
> + * if we need to, we also announce about this channel to the remote
> + * processor (needed in case the driver is exposing an rpmsg service).
> + */
> +static int rpmsg_dev_probe(struct device *dev)
> +{
> +	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> +	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
> +	struct rpmsg_endpoint *ept;
> +	int err;
> +
> +	ept = rpmsg_create_ept(rpdev, rpdrv->callback, NULL, rpdev->src);
> +	if (!ept) {
> +		dev_err(dev, "failed to create endpoint\n");
> +		err = -ENOMEM;
> +		goto out;
> +	}
> +
> +	rpdev->ept = ept;
> +	rpdev->src = ept->addr;
> +
> +	err = rpdrv->probe(rpdev);
> +	if (err) {
> +		dev_err(dev, "%s: failed: %d\n", __func__, err);
> +		rpmsg_destroy_ept(ept);
> +		goto out;
> +	}
> +
> +	if (rpdev->announce_create)
> +		err = rpdev->announce_create(rpdev);
> +out:
> +	return err;
> +}
> +
> +static int rpmsg_dev_remove(struct device *dev)
> +{
> +	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> +	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
> +	int err = 0;
> +
> +	if (rpdev->announce_destroy)
> +		err = rpdev->announce_destroy(rpdev);
> +
> +	rpdrv->remove(rpdev);
> +
> +	rpmsg_destroy_ept(rpdev->ept);
> +
> +	return err;
> +}
> +
> +static struct bus_type rpmsg_bus = {
> +	.name		= "rpmsg",
> +	.match		= rpmsg_dev_match,
> +	.dev_attrs	= rpmsg_dev_attrs,
> +	.uevent		= rpmsg_uevent,
> +	.probe		= rpmsg_dev_probe,
> +	.remove		= rpmsg_dev_remove,
> +};
> +
> +static void rpmsg_release_device(struct device *dev)
> +{
> +	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> +
> +	kfree(rpdev);
> +}
> +
> +int rpmsg_register_device(struct rpmsg_device *rpdev)
> +{
> +	struct device *dev = &rpdev->dev;
> +	int ret;
> +
> +	dev_set_name(&rpdev->dev, "%s:%s",
> +		     dev_name(dev->parent), rpdev->id.name);
> +
> +	rpdev->dev.bus = &rpmsg_bus;
> +	rpdev->dev.release = rpmsg_release_device;
> +
> +	ret = device_register(&rpdev->dev);
> +	if (ret) {
> +		dev_err(dev, "device_register failed: %d\n", ret);
> +		put_device(&rpdev->dev);
> +	}
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL(rpmsg_register_device);
> +
> +/*
> + * match an rpmsg channel with a channel info struct.
> + * this is used to make sure we're not creating rpmsg devices for channels
> + * that already exist.
> + */
> +static int rpmsg_channel_match(struct device *dev, void *data)
> +{
> +	struct rpmsg_channel_info *chinfo = data;
> +	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> +
> +	if (chinfo->src != RPMSG_ADDR_ANY && chinfo->src != rpdev->src)
> +		return 0;
> +
> +	if (chinfo->dst != RPMSG_ADDR_ANY && chinfo->dst != rpdev->dst)
> +		return 0;
> +
> +	if (strncmp(chinfo->name, rpdev->id.name, RPMSG_NAME_SIZE))
> +		return 0;
> +
> +	/* found a match ! */
> +	return 1;
> +}
> +
> +struct device *rpmsg_find_device(struct device *parent,
> +				 struct rpmsg_channel_info *chinfo)
> +{
> +	return device_find_child(parent, chinfo, rpmsg_channel_match);
> +
> +}
> +EXPORT_SYMBOL(rpmsg_find_device);
> +
> +/*
> + * find an existing channel using its name + address properties,
> + * and destroy it
> + */
> +int rpmsg_unregister_device(struct device *parent,
> +			    struct rpmsg_channel_info *chinfo)
> +{
> +	struct device *dev;
> +
> +	dev = rpmsg_find_device(parent, chinfo);
> +	if (!dev)
> +		return -EINVAL;
> +
> +	device_unregister(dev);
> +
> +	put_device(dev);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(rpmsg_unregister_device);
> +
> +/**
> + * __register_rpmsg_driver() - register an rpmsg driver with the rpmsg bus
> + * @rpdrv: pointer to a struct rpmsg_driver
> + * @owner: owning module/driver
> + *
> + * Returns 0 on success, and an appropriate error value on failure.
> + */
> +int __register_rpmsg_driver(struct rpmsg_driver *rpdrv, struct module
> *owner)
> +{
> +	rpdrv->drv.bus = &rpmsg_bus;
> +	rpdrv->drv.owner = owner;
> +	return driver_register(&rpdrv->drv);
> +}
> +EXPORT_SYMBOL(__register_rpmsg_driver);
> +
> +/**
> + * unregister_rpmsg_driver() - unregister an rpmsg driver from the rpmsg
> bus
> + * @rpdrv: pointer to a struct rpmsg_driver
> + *
> + * Returns 0 on success, and an appropriate error value on failure.
> + */
> +void unregister_rpmsg_driver(struct rpmsg_driver *rpdrv)
> +{
> +	driver_unregister(&rpdrv->drv);
> +}
> +EXPORT_SYMBOL(unregister_rpmsg_driver);
> +
> +
> +static int __init rpmsg_init(void)
> +{
> +	int ret;
> +
> +	ret = bus_register(&rpmsg_bus);
> +	if (ret)
> +		pr_err("failed to register rpmsg bus: %d\n", ret);
> +
> +	return ret;
> +}
> +postcore_initcall(rpmsg_init);
> +
> +static void __exit rpmsg_fini(void)
> +{
> +	bus_unregister(&rpmsg_bus);
> +}
> +module_exit(rpmsg_fini);
> +
> +MODULE_DESCRIPTION("remote processor messaging bus");
> +MODULE_LICENSE("GPL v2");
> diff --git a/drivers/rpmsg/rpmsg_internal.h
> b/drivers/rpmsg/rpmsg_internal.h
> new file mode 100644
> index 000000000000..fa91075c7956
> --- /dev/null
> +++ b/drivers/rpmsg/rpmsg_internal.h
> @@ -0,0 +1,45 @@
> +/*
> + * Virtio-based remote processor messaging bus
> + *
> + * Copyright (C) 2011 Texas Instruments, Inc.
> + * Copyright (C) 2011 Google, Inc.
> + *
> + * Ohad Ben-Cohen <ohad@wizery.com>
> + * Brian Swetland <swetland@google.com>
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __RPMSG_INTERNAL_H__
> +#define __RPMSG_INTERNAL_H__
> +
> +#define to_rpmsg_device(d) container_of(d, struct rpmsg_device, dev)
> +#define to_rpmsg_driver(d) container_of(d, struct rpmsg_driver, drv)
> +
> +/**
> + * struct rpmsg_channel_info - internal channel info representation
> + * @name: name of service
> + * @src: local address
> + * @dst: destination address
> + */
> +struct rpmsg_channel_info {
> +	char name[RPMSG_NAME_SIZE];
> +	u32 src;
> +	u32 dst;
> +};
> +
> +int rpmsg_register_device(struct rpmsg_device *rpdev);
> +int rpmsg_unregister_device(struct device *parent,
> +			    struct rpmsg_channel_info *chinfo);
> +
> +struct device *rpmsg_find_device(struct device *parent,
> +				 struct rpmsg_channel_info *chinfo);
> +
> +#endif
> diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c
> b/drivers/rpmsg/virtio_rpmsg_bus.c
> index 5cadb75a225d..779c54304774 100644
> --- a/drivers/rpmsg/virtio_rpmsg_bus.c
> +++ b/drivers/rpmsg/virtio_rpmsg_bus.c
> @@ -35,6 +35,8 @@
>  #include <linux/mutex.h>
>  #include <linux/of_device.h>
> 
> +#include "rpmsg_internal.h"
> +
>  /**
>   * struct virtproc_info - virtual remote processor state
>   * @vdev:	the virtio device
> @@ -73,21 +75,6 @@ struct virtproc_info {
>  	struct rpmsg_endpoint *ns_ept;
>  };
> 
> -/**
> - * struct rpmsg_channel_info - internal channel info representation
> - * @name: name of service
> - * @src: local address
> - * @dst: destination address
> - */
> -struct rpmsg_channel_info {
> -	char name[RPMSG_NAME_SIZE];
> -	u32 src;
> -	u32 dst;
> -};
> -
> -#define to_rpmsg_device(d) container_of(d, struct rpmsg_device, dev)
> -#define to_rpmsg_driver(d) container_of(d, struct rpmsg_driver, drv)
> -
>  /*
>   * We're allocating buffers of 512 bytes each for communications. The
>   * number of buffers will be computed from the number of buffers
> supported
> @@ -129,72 +116,6 @@ static int virtio_rpmsg_trysendto(struct
> rpmsg_endpoint *ept, void *data,
>  				  int len, u32 dst);
>  static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32
> src,
>  					   u32 dst, void *data, int len);
> -static int rpmsg_register_device(struct rpmsg_device *rpdev);
> -
> -/* sysfs show configuration fields */
> -#define rpmsg_show_attr(field, path, format_string)			\
> -static ssize_t								\
> -field##_show(struct device *dev,					\
> -			struct device_attribute *attr, char *buf)	\
> -{									\
> -	struct rpmsg_device *rpdev = to_rpmsg_device(dev);		\
> -									\
> -	return sprintf(buf, format_string, rpdev->path);		\
> -}
> -
> -/* for more info, see Documentation/ABI/testing/sysfs-bus-rpmsg */
> -rpmsg_show_attr(name, id.name, "%s\n");
> -rpmsg_show_attr(src, src, "0x%x\n");
> -rpmsg_show_attr(dst, dst, "0x%x\n");
> -rpmsg_show_attr(announce, announce ? "true" : "false", "%s\n");
> -
> -static ssize_t modalias_show(struct device *dev,
> -			     struct device_attribute *attr, char *buf)
> -{
> -	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> -
> -	return sprintf(buf, RPMSG_DEVICE_MODALIAS_FMT "\n", rpdev-
> >id.name);
> -}
> -
> -static struct device_attribute rpmsg_dev_attrs[] = {
> -	__ATTR_RO(name),
> -	__ATTR_RO(modalias),
> -	__ATTR_RO(dst),
> -	__ATTR_RO(src),
> -	__ATTR_RO(announce),
> -	__ATTR_NULL
> -};
> -
> -/* rpmsg devices and drivers are matched using the service name */
> -static inline int rpmsg_id_match(const struct rpmsg_device *rpdev,
> -				 const struct rpmsg_device_id *id)
> -{
> -	return strncmp(id->name, rpdev->id.name, RPMSG_NAME_SIZE) ==
> 0;
> -}
> -
> -/* match rpmsg channel and rpmsg driver */
> -static int rpmsg_dev_match(struct device *dev, struct device_driver *drv)
> -{
> -	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> -	struct rpmsg_driver *rpdrv = to_rpmsg_driver(drv);
> -	const struct rpmsg_device_id *ids = rpdrv->id_table;
> -	unsigned int i;
> -
> -	if (ids)
> -		for (i = 0; ids[i].name[0]; i++)
> -			if (rpmsg_id_match(rpdev, &ids[i]))
> -				return 1;
> -
> -	return of_driver_match_device(dev, drv);
> -}
> -
> -static int rpmsg_uevent(struct device *dev, struct kobj_uevent_env *env)
> -{
> -	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> -
> -	return add_uevent_var(env, "MODALIAS="
> RPMSG_DEVICE_MODALIAS_FMT,
> -					rpdev->id.name);
> -}
> 
>  /**
>   * __ept_release() - deallocate an rpmsg endpoint
> @@ -266,53 +187,6 @@ free_ept:
>  	return NULL;
>  }
> 
> -/**
> - * rpmsg_create_ept() - create a new rpmsg_endpoint
> - * @rpdev: rpmsg channel device
> - * @cb: rx callback handler
> - * @priv: private data for the driver's use
> - * @addr: local rpmsg address to bind with @cb
> - *
> - * Every rpmsg address in the system is bound to an rx callback (so when
> - * inbound messages arrive, they are dispatched by the rpmsg bus using the
> - * appropriate callback handler) by means of an rpmsg_endpoint struct.
> - *
> - * This function allows drivers to create such an endpoint, and by that,
> - * bind a callback, and possibly some private data too, to an rpmsg address
> - * (either one that is known in advance, or one that will be dynamically
> - * assigned for them).
> - *
> - * Simple rpmsg drivers need not call rpmsg_create_ept, because an
> endpoint
> - * is already created for them when they are probed by the rpmsg bus
> - * (using the rx callback provided when they registered to the rpmsg bus).
> - *
> - * So things should just work for simple drivers: they already have an
> - * endpoint, their rx callback is bound to their rpmsg address, and when
> - * relevant inbound messages arrive (i.e. messages which their dst address
> - * equals to the src address of their rpmsg channel), the driver's handler
> - * is invoked to process it.
> - *
> - * That said, more complicated drivers might do need to allocate
> - * additional rpmsg addresses, and bind them to different rx callbacks.
> - * To accomplish that, those drivers need to call this function.
> - *
> - * Drivers should provide their @rpdev channel (so the new endpoint would
> belong
> - * to the same remote processor their channel belongs to), an rx callback
> - * function, an optional private data (which is provided back when the
> - * rx callback is invoked), and an address they want to bind with the
> - * callback. If @addr is RPMSG_ADDR_ANY, then rpmsg_create_ept will
> - * dynamically assign them an available rpmsg address (drivers should have
> - * a very good reason why not to always use RPMSG_ADDR_ANY here).
> - *
> - * Returns a pointer to the endpoint on success, or NULL on error.
> - */
> -struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev,
> -					rpmsg_rx_cb_t cb, void *priv, u32
> addr)
> -{
> -	return rpdev->create_ept(rpdev, cb, priv, addr);
> -}
> -EXPORT_SYMBOL(rpmsg_create_ept);
> -
>  static struct rpmsg_endpoint *virtio_rpmsg_create_ept(struct
> rpmsg_device *rpdev,
>  						      rpmsg_rx_cb_t cb,
>  						      void *priv, u32 addr)
> @@ -346,62 +220,11 @@ __rpmsg_destroy_ept(struct virtproc_info *vrp,
> struct rpmsg_endpoint *ept)
>  	kref_put(&ept->refcount, __ept_release);
>  }
> 
> -/**
> - * rpmsg_destroy_ept() - destroy an existing rpmsg endpoint
> - * @ept: endpoing to destroy
> - *
> - * Should be used by drivers to destroy an rpmsg endpoint previously
> - * created with rpmsg_create_ept().
> - */
> -void rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
> -{
> -	ept->rpdev->destroy_ept(ept);
> -}
> -EXPORT_SYMBOL(rpmsg_destroy_ept);
> -
>  static void virtio_rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
>  {
>  	__rpmsg_destroy_ept(ept->rpdev->vrp, ept);
>  }
> 
> -/*
> - * when an rpmsg driver is probed with a channel, we seamlessly create
> - * it an endpoint, binding its rx callback to a unique local rpmsg
> - * address.
> - *
> - * if we need to, we also announce about this channel to the remote
> - * processor (needed in case the driver is exposing an rpmsg service).
> - */
> -static int rpmsg_dev_probe(struct device *dev)
> -{
> -	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> -	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
> -	struct rpmsg_endpoint *ept;
> -	int err;
> -
> -	ept = rpmsg_create_ept(rpdev, rpdrv->callback, NULL, rpdev->src);
> -	if (!ept) {
> -		dev_err(dev, "failed to create endpoint\n");
> -		err = -ENOMEM;
> -		goto out;
> -	}
> -
> -	rpdev->ept = ept;
> -	rpdev->src = ept->addr;
> -
> -	err = rpdrv->probe(rpdev);
> -	if (err) {
> -		dev_err(dev, "%s: failed: %d\n", __func__, err);
> -		rpmsg_destroy_ept(ept);
> -		goto out;
> -	}
> -
> -	if (rpdev->announce_create)
> -		err = rpdev->announce_create(rpdev);
> -out:
> -	return err;
> -}
> -
>  static int virtio_rpmsg_announce_create(struct rpmsg_device *rpdev)
>  {
>  	struct virtproc_info *vrp = rpdev->vrp;
> @@ -448,88 +271,6 @@ static int virtio_rpmsg_announce_destroy(struct
> rpmsg_device *rpdev)
>  	return err;
>  }
> 
> -static int rpmsg_dev_remove(struct device *dev)
> -{
> -	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> -	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
> -	int err = 0;
> -
> -	if (rpdev->announce_destroy)
> -		err = rpdev->announce_destroy(rpdev);
> -
> -	rpdrv->remove(rpdev);
> -
> -	rpmsg_destroy_ept(rpdev->ept);
> -
> -	return err;
> -}
> -
> -static struct bus_type rpmsg_bus = {
> -	.name		= "rpmsg",
> -	.match		= rpmsg_dev_match,
> -	.dev_attrs	= rpmsg_dev_attrs,
> -	.uevent		= rpmsg_uevent,
> -	.probe		= rpmsg_dev_probe,
> -	.remove		= rpmsg_dev_remove,
> -};
> -
> -/**
> - * __register_rpmsg_driver() - register an rpmsg driver with the rpmsg bus
> - * @rpdrv: pointer to a struct rpmsg_driver
> - * @owner: owning module/driver
> - *
> - * Returns 0 on success, and an appropriate error value on failure.
> - */
> -int __register_rpmsg_driver(struct rpmsg_driver *rpdrv, struct module
> *owner)
> -{
> -	rpdrv->drv.bus = &rpmsg_bus;
> -	rpdrv->drv.owner = owner;
> -	return driver_register(&rpdrv->drv);
> -}
> -EXPORT_SYMBOL(__register_rpmsg_driver);
> -
> -/**
> - * unregister_rpmsg_driver() - unregister an rpmsg driver from the rpmsg
> bus
> - * @rpdrv: pointer to a struct rpmsg_driver
> - *
> - * Returns 0 on success, and an appropriate error value on failure.
> - */
> -void unregister_rpmsg_driver(struct rpmsg_driver *rpdrv)
> -{
> -	driver_unregister(&rpdrv->drv);
> -}
> -EXPORT_SYMBOL(unregister_rpmsg_driver);
> -
> -static void rpmsg_release_device(struct device *dev)
> -{
> -	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> -
> -	kfree(rpdev);
> -}
> -
> -/*
> - * match an rpmsg channel with a channel info struct.
> - * this is used to make sure we're not creating rpmsg devices for channels
> - * that already exist.
> - */
> -static int rpmsg_device_match(struct device *dev, void *data)
> -{
> -	struct rpmsg_channel_info *chinfo = data;
> -	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> -
> -	if (chinfo->src != RPMSG_ADDR_ANY && chinfo->src != rpdev->src)
> -		return 0;
> -
> -	if (chinfo->dst != RPMSG_ADDR_ANY && chinfo->dst != rpdev->dst)
> -		return 0;
> -
> -	if (strncmp(chinfo->name, rpdev->id.name, RPMSG_NAME_SIZE))
> -		return 0;
> -
> -	/* found a match ! */
> -	return 1;
> -}
> -
>  static const struct rpmsg_device virtio_rpmsg_ops = {
>  	.create_ept = virtio_rpmsg_create_ept,
>  	.destroy_ept = virtio_rpmsg_destroy_ept,
> @@ -556,7 +297,7 @@ static struct rpmsg_device
> *rpmsg_create_channel(struct virtproc_info *vrp,
>  	int ret;
> 
>  	/* make sure a similar channel doesn't already exist */
> -	tmp = device_find_child(dev, chinfo, rpmsg_device_match);
> +	tmp = rpmsg_find_device(dev, chinfo);
>  	if (tmp) {
>  		/* decrement the matched device's refcount back */
>  		put_device(tmp);
> @@ -592,47 +333,6 @@ static struct rpmsg_device
> *rpmsg_create_channel(struct virtproc_info *vrp,
>  	return rpdev;
>  }
> 
> -static int rpmsg_register_device(struct rpmsg_device *rpdev)
> -{
> -	struct device *dev = &rpdev->dev;
> -	int ret;
> -
> -	dev_set_name(&rpdev->dev, "%s:%s",
> -		     dev_name(dev->parent), rpdev->id.name);
> -
> -	rpdev->dev.bus = &rpmsg_bus;
> -	rpdev->dev.release = rpmsg_release_device;
> -
> -	ret = device_register(&rpdev->dev);
> -	if (ret) {
> -		dev_err(dev, "device_register failed: %d\n", ret);
> -		put_device(&rpdev->dev);
> -	}
> -
> -	return ret;
> -}
> -
> -/*
> - * find an existing channel using its name + address properties,
> - * and destroy it
> - */
> -static int rpmsg_destroy_channel(struct virtproc_info *vrp,
> -				 struct rpmsg_channel_info *chinfo)
> -{
> -	struct virtio_device *vdev = vrp->vdev;
> -	struct device *dev;
> -
> -	dev = device_find_child(&vdev->dev, chinfo, rpmsg_device_match);
> -	if (!dev)
> -		return -EINVAL;
> -
> -	device_unregister(dev);
> -
> -	put_device(dev);
> -
> -	return 0;
> -}
> -
>  /* super simple buffer "allocator" that is just enough for now */
>  static void *get_a_tx_buf(struct virtproc_info *vrp)
>  {
> @@ -844,31 +544,6 @@ out:
>  	return err;
>  }
> 
> -/**
> - * rpmsg_send() - send a message across to the remote processor
> - * @ept: the rpmsg endpoint
> - * @data: payload of message
> - * @len: length of payload
> - *
> - * This function sends @data of length @len on the @ept endpoint.
> - * The message will be sent to the remote processor which the @ept
> - * endpoint belongs to, using @ept's address and its associated rpmsg
> - * device destination addresses.
> - * In case there are no TX buffers available, the function will block until
> - * one becomes available, or a timeout of 15 seconds elapses. When the
> latter
> - * happens, -ERESTARTSYS is returned.
> - *
> - * Can only be called from process context (for now).
> - *
> - * Returns 0 on success and an appropriate error value on failure.
> - */
> -int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
> -{
> -	struct rpmsg_device *rpdev = ept->rpdev;
> -
> -	return rpdev->send(ept, data, len);
> -}
> -
>  static int virtio_rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
>  {
>  	struct rpmsg_device *rpdev = ept->rpdev;
> @@ -877,32 +552,6 @@ static int virtio_rpmsg_send(struct rpmsg_endpoint
> *ept, void *data, int len)
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
>  }
> 
> -/**
> - * rpmsg_sendto() - send a message across to the remote processor, specify
> dst
> - * @ept: the rpmsg endpoint
> - * @data: payload of message
> - * @len: length of payload
> - * @dst: destination address
> - *
> - * This function sends @data of length @len to the remote @dst address.
> - * The message will be sent to the remote processor which the @ept
> - * endpoint belongs to, using @ept's address as source.
> - * In case there are no TX buffers available, the function will block until
> - * one becomes available, or a timeout of 15 seconds elapses. When the
> latter
> - * happens, -ERESTARTSYS is returned.
> - *
> - * Can only be called from process context (for now).
> - *
> - * Returns 0 on success and an appropriate error value on failure.
> - */
> -int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
> -{
> -	struct rpmsg_device *rpdev = ept->rpdev;
> -
> -	return rpdev->sendto(ept, data, len, dst);
> -}
> -EXPORT_SYMBOL(rpmsg_sendto);
> -
>  static int virtio_rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int
> len,
>  			       u32 dst)
>  {
> @@ -912,35 +561,6 @@ static int virtio_rpmsg_sendto(struct
> rpmsg_endpoint *ept, void *data, int len,
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
>  }
> 
> -/**
> - * rpmsg_send_offchannel() - send a message using explicit src/dst
> addresses
> - * @ept: the rpmsg endpoint
> - * @src: source address
> - * @dst: destination address
> - * @data: payload of message
> - * @len: length of payload
> - *
> - * This function sends @data of length @len to the remote @dst address,
> - * and uses @src as the source address.
> - * The message will be sent to the remote processor which the @ept
> - * endpoint belongs to.
> - * In case there are no TX buffers available, the function will block until
> - * one becomes available, or a timeout of 15 seconds elapses. When the
> latter
> - * happens, -ERESTARTSYS is returned.
> - *
> - * Can only be called from process context (for now).
> - *
> - * Returns 0 on success and an appropriate error value on failure.
> - */
> -int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
> -			  void *data, int len)
> -{
> -	struct rpmsg_device *rpdev = ept->rpdev;
> -
> -	return rpdev->send_offchannel(ept, src, dst, data, len);
> -}
> -EXPORT_SYMBOL(rpmsg_send_offchannel);
> -
>  static int virtio_rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32
> src,
>  					u32 dst, void *data, int len)
>  {
> @@ -949,31 +569,6 @@ static int virtio_rpmsg_send_offchannel(struct
> rpmsg_endpoint *ept, u32 src,
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
>  }
> 
> -/**
> - * rpmsg_send() - send a message across to the remote processor
> - * @ept: the rpmsg endpoint
> - * @data: payload of message
> - * @len: length of payload
> - *
> - * This function sends @data of length @len on the @ept endpoint.
> - * The message will be sent to the remote processor which the @ept
> - * endpoint belongs to, using @ept's addres as source and its associated
> - * rpdev's address as destination.
> - * In case there are no TX buffers available, the function will immediately
> - * return -ENOMEM without waiting until one becomes available.
> - *
> - * Can only be called from process context (for now).
> - *
> - * Returns 0 on success and an appropriate error value on failure.
> - */
> -int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
> -{
> -	struct rpmsg_device *rpdev = ept->rpdev;
> -
> -	return rpdev->trysend(ept, data, len);
> -}
> -EXPORT_SYMBOL(rpmsg_trysend);
> -
>  static int virtio_rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int
> len)
>  {
>  	struct rpmsg_device *rpdev = ept->rpdev;
> @@ -982,31 +577,6 @@ static int virtio_rpmsg_trysend(struct
> rpmsg_endpoint *ept, void *data, int len)
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
>  }
> 
> -/**
> - * rpmsg_sendto() - send a message across to the remote processor, specify
> dst
> - * @ept: the rpmsg endpoint
> - * @data: payload of message
> - * @len: length of payload
> - * @dst: destination address
> - *
> - * This function sends @data of length @len to the remote @dst address.
> - * The message will be sent to the remote processor which the @ept
> - * endpoint belongs to, using @ept's address as source.
> - * In case there are no TX buffers available, the function will immediately
> - * return -ENOMEM without waiting until one becomes available.
> - *
> - * Can only be called from process context (for now).
> - *
> - * Returns 0 on success and an appropriate error value on failure.
> - */
> -int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32
> dst)
> -{
> -	struct rpmsg_device *rpdev = ept->rpdev;
> -
> -	return rpdev->trysendto(ept, data, len, dst);
> -}
> -EXPORT_SYMBOL(rpmsg_trysendto);
> -
>  static int virtio_rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data,
>  				  int len, u32 dst)
>  {
> @@ -1016,34 +586,6 @@ static int virtio_rpmsg_trysendto(struct
> rpmsg_endpoint *ept, void *data,
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
>  }
> 
> -/**
> - * rpmsg_send_offchannel() - send a message using explicit src/dst
> addresses
> - * @ept: the rpmsg endpoint
> - * @src: source address
> - * @dst: destination address
> - * @data: payload of message
> - * @len: length of payload
> - *
> - * This function sends @data of length @len to the remote @dst address,
> - * and uses @src as the source address.
> - * The message will be sent to the remote processor which the @ept
> - * endpoint belongs to.
> - * In case there are no TX buffers available, the function will immediately
> - * return -ENOMEM without waiting until one becomes available.
> - *
> - * Can only be called from process context (for now).
> - *
> - * Returns 0 on success and an appropriate error value on failure.
> - */
> -int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32
> dst,
> -			     void *data, int len)
> -{
> -	struct rpmsg_device *rpdev = ept->rpdev;
> -
> -	return rpdev->trysend_offchannel(ept, src, dst, data, len);
> -}
> -EXPORT_SYMBOL(rpmsg_trysend_offchannel);
> -
>  static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32
> src,
>  					   u32 dst, void *data, int len)
>  {
> @@ -1208,7 +750,7 @@ static void rpmsg_ns_cb(struct rpmsg_device
> *rpdev, void *data, int len,
>  	chinfo.dst = msg->addr;
> 
>  	if (msg->flags & RPMSG_NS_DESTROY) {
> -		ret = rpmsg_destroy_channel(vrp, &chinfo);
> +		ret = rpmsg_unregister_device(&vrp->vdev->dev, &chinfo);
>  		if (ret)
>  			dev_err(dev, "rpmsg_destroy_channel failed: %d\n",
> ret);
>  	} else {
> @@ -1393,17 +935,9 @@ static int __init rpmsg_init(void)
>  {
>  	int ret;
> 
> -	ret = bus_register(&rpmsg_bus);
> -	if (ret) {
> -		pr_err("failed to register rpmsg bus: %d\n", ret);
> -		return ret;
> -	}
> -
>  	ret = register_virtio_driver(&virtio_ipc_driver);
> -	if (ret) {
> +	if (ret)
>  		pr_err("failed to register virtio driver: %d\n", ret);
> -		bus_unregister(&rpmsg_bus);
> -	}
> 
>  	return ret;
>  }
> @@ -1412,7 +946,6 @@ subsys_initcall(rpmsg_init);
>  static void __exit rpmsg_fini(void)
>  {
>  	unregister_virtio_driver(&virtio_ipc_driver);
> -	bus_unregister(&rpmsg_bus);
>  }
>  module_exit(rpmsg_fini);
> 
> --
> 2.5.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-remoteproc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 54+ messages in thread

* [PATCH 08/14] rpmsg: Split rpmsg core and virtio backend
@ 2016-08-18 11:59     ` Loic PALLARDY
  0 siblings, 0 replies; 54+ messages in thread
From: Loic PALLARDY @ 2016-08-18 11:59 UTC (permalink / raw)
  To: linux-arm-kernel



> -----Original Message-----
> From: linux-remoteproc-owner at vger.kernel.org [mailto:linux-remoteproc-
> owner at vger.kernel.org] On Behalf Of Bjorn Andersson
> Sent: Tuesday, August 16, 2016 2:17 AM
> To: Ohad Ben-Cohen <ohad@wizery.com>; Bjorn Andersson
> <bjorn.andersson@linaro.org>
> Cc: linux-remoteproc at vger.kernel.org; linux-arm-msm at vger.kernel.org;
> linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org;
> Sricharan R <sricharan@codeaurora.org>
> Subject: [PATCH 08/14] rpmsg: Split rpmsg core and virtio backend
> 
> Extract the generic rpmsg core functionality from the virtio rpmsg
> implementation, splitting the implementation in a rpmsg core and a
> virtio backend.
> 
> Based on initial work by Sricharan R <sricharan@codeaurora.org>
> 
> Cc: Sricharan R <sricharan@codeaurora.org>
> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> ---
>  drivers/rpmsg/Kconfig            |   4 +
>  drivers/rpmsg/Makefile           |   3 +-
>  drivers/rpmsg/rpmsg_core.c       | 513
> +++++++++++++++++++++++++++++++++++++++
>  drivers/rpmsg/rpmsg_internal.h   |  45 ++++
>  drivers/rpmsg/virtio_rpmsg_bus.c | 477 +-----------------------------------
Hi Bjorn,

Could you please regenerate the patch with  option -M (of git formatpatch) to detect file renames.
It will provide better visibility of differences between virtio_rpmsg_bus.c and rpmsg_core.c.

>  5 files changed, 569 insertions(+), 473 deletions(-)
>  create mode 100644 drivers/rpmsg/rpmsg_core.c
>  create mode 100644 drivers/rpmsg/rpmsg_internal.h
> 
> diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig
> index 69a219387582..40614be88c97 100644
> --- a/drivers/rpmsg/Kconfig
> +++ b/drivers/rpmsg/Kconfig
> @@ -3,6 +3,10 @@ menu "Rpmsg drivers"
>  # RPMSG always gets selected by whoever wants it
>  config RPMSG
>  	tristate
> +
> +config RPMSG_VIRTIO
> +	tristate
> +	select RPMSG
>  	select VIRTIO
>  	select VIRTUALIZATION
> 
Remoteproc Kconfig should be changed too to select RPMSG_VIRTIO instead of RPMSG.

Regards,
Loic

> diff --git a/drivers/rpmsg/Makefile b/drivers/rpmsg/Makefile
> index 7617fcb8259f..383213417a00 100644
> --- a/drivers/rpmsg/Makefile
> +++ b/drivers/rpmsg/Makefile
> @@ -1 +1,2 @@
> -obj-$(CONFIG_RPMSG)	+= virtio_rpmsg_bus.o
> +obj-$(CONFIG_RPMSG)	+= rpmsg_core.o
> +obj-$(CONFIG_RPMSG_VIRTIO) += virtio_rpmsg_bus.o
> diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
> new file mode 100644
> index 000000000000..73bbc5ea5778
> --- /dev/null
> +++ b/drivers/rpmsg/rpmsg_core.c
> @@ -0,0 +1,513 @@
> +/*
> + * Virtio-based remote processor messaging bus
> + *
> + * Copyright (C) 2011 Texas Instruments, Inc.
> + * Copyright (C) 2011 Google, Inc.
> + *
> + * Ohad Ben-Cohen <ohad@wizery.com>
> + * Brian Swetland <swetland@google.com>
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#define pr_fmt(fmt) "%s: " fmt, __func__
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/virtio.h>
> +#include <linux/virtio_ids.h>
> +#include <linux/virtio_config.h>
> +#include <linux/scatterlist.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/slab.h>
> +#include <linux/idr.h>
> +#include <linux/jiffies.h>
> +#include <linux/sched.h>
> +#include <linux/wait.h>
> +#include <linux/rpmsg.h>
> +#include <linux/mutex.h>
> +#include <linux/of_device.h>
> +
> +#include "rpmsg_internal.h"
> +
> +/**
> + * rpmsg_create_ept() - create a new rpmsg_endpoint
> + * @rpdev: rpmsg channel device
> + * @cb: rx callback handler
> + * @priv: private data for the driver's use
> + * @addr: local rpmsg address to bind with @cb
> + *
> + * Every rpmsg address in the system is bound to an rx callback (so when
> + * inbound messages arrive, they are dispatched by the rpmsg bus using the
> + * appropriate callback handler) by means of an rpmsg_endpoint struct.
> + *
> + * This function allows drivers to create such an endpoint, and by that,
> + * bind a callback, and possibly some private data too, to an rpmsg address
> + * (either one that is known in advance, or one that will be dynamically
> + * assigned for them).
> + *
> + * Simple rpmsg drivers need not call rpmsg_create_ept, because an
> endpoint
> + * is already created for them when they are probed by the rpmsg bus
> + * (using the rx callback provided when they registered to the rpmsg bus).
> + *
> + * So things should just work for simple drivers: they already have an
> + * endpoint, their rx callback is bound to their rpmsg address, and when
> + * relevant inbound messages arrive (i.e. messages which their dst address
> + * equals to the src address of their rpmsg channel), the driver's handler
> + * is invoked to process it.
> + *
> + * That said, more complicated drivers might do need to allocate
> + * additional rpmsg addresses, and bind them to different rx callbacks.
> + * To accomplish that, those drivers need to call this function.
> + *
> + * Drivers should provide their @rpdev channel (so the new endpoint would
> belong
> + * to the same remote processor their channel belongs to), an rx callback
> + * function, an optional private data (which is provided back when the
> + * rx callback is invoked), and an address they want to bind with the
> + * callback. If @addr is RPMSG_ADDR_ANY, then rpmsg_create_ept will
> + * dynamically assign them an available rpmsg address (drivers should have
> + * a very good reason why not to always use RPMSG_ADDR_ANY here).
> + *
> + * Returns a pointer to the endpoint on success, or NULL on error.
> + */
> +struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev,
> +				rpmsg_rx_cb_t cb, void *priv, u32 addr)
> +{
> +	return rpdev->create_ept(rpdev, cb, priv, addr);
> +}
> +EXPORT_SYMBOL(rpmsg_create_ept);
> +
> +/**
> + * rpmsg_destroy_ept() - destroy an existing rpmsg endpoint
> + * @ept: endpoing to destroy
> + *
> + * Should be used by drivers to destroy an rpmsg endpoint previously
> + * created with rpmsg_create_ept().
> + */
> +void rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
> +{
> +	ept->rpdev->destroy_ept(ept);
> +}
> +EXPORT_SYMBOL(rpmsg_destroy_ept);
> +
> +/**
> + * rpmsg_send() - send a message across to the remote processor
> + * @ept: the rpmsg endpoint
> + * @data: payload of message
> + * @len: length of payload
> + *
> + * This function sends @data of length @len on the @ept endpoint.
> + * The message will be sent to the remote processor which the @ept
> + * endpoint belongs to, using @ept's address and its associated rpmsg
> + * device destination addresses.
> + * In case there are no TX buffers available, the function will block until
> + * one becomes available, or a timeout of 15 seconds elapses. When the
> latter
> + * happens, -ERESTARTSYS is returned.
> + *
> + * Can only be called from process context (for now).
> + *
> + * Returns 0 on success and an appropriate error value on failure.
> + */
> +int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
> +{
> +	struct rpmsg_device *rpdev = ept->rpdev;
> +
> +	return rpdev->send(ept, data, len);
> +}
> +
> +/**
> + * rpmsg_sendto() - send a message across to the remote processor,
> specify dst
> + * @ept: the rpmsg endpoint
> + * @data: payload of message
> + * @len: length of payload
> + * @dst: destination address
> + *
> + * This function sends @data of length @len to the remote @dst address.
> + * The message will be sent to the remote processor which the @ept
> + * endpoint belongs to, using @ept's address as source.
> + * In case there are no TX buffers available, the function will block until
> + * one becomes available, or a timeout of 15 seconds elapses. When the
> latter
> + * happens, -ERESTARTSYS is returned.
> + *
> + * Can only be called from process context (for now).
> + *
> + * Returns 0 on success and an appropriate error value on failure.
> + */
> +int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
> +{
> +	struct rpmsg_device *rpdev = ept->rpdev;
> +
> +	return rpdev->sendto(ept, data, len, dst);
> +}
> +EXPORT_SYMBOL(rpmsg_sendto);
> +
> +/**
> + * rpmsg_send_offchannel() - send a message using explicit src/dst
> addresses
> + * @ept: the rpmsg endpoint
> + * @src: source address
> + * @dst: destination address
> + * @data: payload of message
> + * @len: length of payload
> + *
> + * This function sends @data of length @len to the remote @dst address,
> + * and uses @src as the source address.
> + * The message will be sent to the remote processor which the @ept
> + * endpoint belongs to.
> + * In case there are no TX buffers available, the function will block until
> + * one becomes available, or a timeout of 15 seconds elapses. When the
> latter
> + * happens, -ERESTARTSYS is returned.
> + *
> + * Can only be called from process context (for now).
> + *
> + * Returns 0 on success and an appropriate error value on failure.
> + */
> +int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
> +			  void *data, int len)
> +{
> +	struct rpmsg_device *rpdev = ept->rpdev;
> +
> +	return rpdev->send_offchannel(ept, src, dst, data, len);
> +}
> +EXPORT_SYMBOL(rpmsg_send_offchannel);
> +
> +/**
> + * rpmsg_send() - send a message across to the remote processor
> + * @ept: the rpmsg endpoint
> + * @data: payload of message
> + * @len: length of payload
> + *
> + * This function sends @data of length @len on the @ept endpoint.
> + * The message will be sent to the remote processor which the @ept
> + * endpoint belongs to, using @ept's address as source and its associated
> + * rpdev's address as destination.
> + * In case there are no TX buffers available, the function will immediately
> + * return -ENOMEM without waiting until one becomes available.
> + *
> + * Can only be called from process context (for now).
> + *
> + * Returns 0 on success and an appropriate error value on failure.
> + */
> +int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
> +{
> +	struct rpmsg_device *rpdev = ept->rpdev;
> +
> +	return rpdev->trysend(ept, data, len);
> +}
> +EXPORT_SYMBOL(rpmsg_trysend);
> +
> +/**
> + * rpmsg_sendto() - send a message across to the remote processor,
> specify dst
> + * @ept: the rpmsg endpoint
> + * @data: payload of message
> + * @len: length of payload
> + * @dst: destination address
> + *
> + * This function sends @data of length @len to the remote @dst address.
> + * The message will be sent to the remote processor which the @ept
> + * endpoint belongs to, using @ept's address as source.
> + * In case there are no TX buffers available, the function will immediately
> + * return -ENOMEM without waiting until one becomes available.
> + *
> + * Can only be called from process context (for now).
> + *
> + * Returns 0 on success and an appropriate error value on failure.
> + */
> +int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32
> dst)
> +{
> +	struct rpmsg_device *rpdev = ept->rpdev;
> +
> +	return rpdev->trysendto(ept, data, len, dst);
> +}
> +EXPORT_SYMBOL(rpmsg_trysendto);
> +
> +/**
> + * rpmsg_send_offchannel() - send a message using explicit src/dst
> addresses
> + * @ept: the rpmsg endpoint
> + * @src: source address
> + * @dst: destination address
> + * @data: payload of message
> + * @len: length of payload
> + *
> + * This function sends @data of length @len to the remote @dst address,
> + * and uses @src as the source address.
> + * The message will be sent to the remote processor which the @ept
> + * endpoint belongs to.
> + * In case there are no TX buffers available, the function will immediately
> + * return -ENOMEM without waiting until one becomes available.
> + *
> + * Can only be called from process context (for now).
> + *
> + * Returns 0 on success and an appropriate error value on failure.
> + */
> +int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32
> dst,
> +			     void *data, int len)
> +{
> +	struct rpmsg_device *rpdev = ept->rpdev;
> +
> +	return rpdev->trysend_offchannel(ept, src, dst, data, len);
> +}
> +EXPORT_SYMBOL(rpmsg_trysend_offchannel);
> +
> +/* sysfs show configuration fields */
> +#define rpmsg_show_attr(field, path, format_string)			\
> +static ssize_t								\
> +field##_show(struct device *dev,					\
> +			struct device_attribute *attr, char *buf)	\
> +{									\
> +	struct rpmsg_device *rpdev = to_rpmsg_device(dev);		\
> +									\
> +	return sprintf(buf, format_string, rpdev->path);		\
> +}
> +
> +/* for more info, see Documentation/ABI/testing/sysfs-bus-rpmsg */
> +rpmsg_show_attr(name, id.name, "%s\n");
> +rpmsg_show_attr(src, src, "0x%x\n");
> +rpmsg_show_attr(dst, dst, "0x%x\n");
> +rpmsg_show_attr(announce, announce ? "true" : "false", "%s\n");
> +
> +static ssize_t modalias_show(struct device *dev,
> +			     struct device_attribute *attr, char *buf)
> +{
> +	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> +
> +	return sprintf(buf, RPMSG_DEVICE_MODALIAS_FMT "\n", rpdev-
> >id.name);
> +}
> +
> +static struct device_attribute rpmsg_dev_attrs[] = {
> +	__ATTR_RO(name),
> +	__ATTR_RO(modalias),
> +	__ATTR_RO(dst),
> +	__ATTR_RO(src),
> +	__ATTR_RO(announce),
> +	__ATTR_NULL
> +};
> +
> +/* rpmsg devices and drivers are matched using the service name */
> +static inline int rpmsg_id_match(const struct rpmsg_device *rpdev,
> +				  const struct rpmsg_device_id *id)
> +{
> +	return strncmp(id->name, rpdev->id.name, RPMSG_NAME_SIZE) ==
> 0;
> +}
> +
> +/* match rpmsg channel and rpmsg driver */
> +static int rpmsg_dev_match(struct device *dev, struct device_driver *drv)
> +{
> +	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> +	struct rpmsg_driver *rpdrv = to_rpmsg_driver(drv);
> +	const struct rpmsg_device_id *ids = rpdrv->id_table;
> +	unsigned int i;
> +
> +	if (ids)
> +		for (i = 0; ids[i].name[0]; i++)
> +			if (rpmsg_id_match(rpdev, &ids[i]))
> +				return 1;
> +
> +	return of_driver_match_device(dev, drv);
> +}
> +
> +static int rpmsg_uevent(struct device *dev, struct kobj_uevent_env *env)
> +{
> +	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> +
> +	return add_uevent_var(env, "MODALIAS="
> RPMSG_DEVICE_MODALIAS_FMT,
> +					rpdev->id.name);
> +}
> +
> +/*
> + * when an rpmsg driver is probed with a channel, we seamlessly create
> + * it an endpoint, binding its rx callback to a unique local rpmsg
> + * address.
> + *
> + * if we need to, we also announce about this channel to the remote
> + * processor (needed in case the driver is exposing an rpmsg service).
> + */
> +static int rpmsg_dev_probe(struct device *dev)
> +{
> +	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> +	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
> +	struct rpmsg_endpoint *ept;
> +	int err;
> +
> +	ept = rpmsg_create_ept(rpdev, rpdrv->callback, NULL, rpdev->src);
> +	if (!ept) {
> +		dev_err(dev, "failed to create endpoint\n");
> +		err = -ENOMEM;
> +		goto out;
> +	}
> +
> +	rpdev->ept = ept;
> +	rpdev->src = ept->addr;
> +
> +	err = rpdrv->probe(rpdev);
> +	if (err) {
> +		dev_err(dev, "%s: failed: %d\n", __func__, err);
> +		rpmsg_destroy_ept(ept);
> +		goto out;
> +	}
> +
> +	if (rpdev->announce_create)
> +		err = rpdev->announce_create(rpdev);
> +out:
> +	return err;
> +}
> +
> +static int rpmsg_dev_remove(struct device *dev)
> +{
> +	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> +	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
> +	int err = 0;
> +
> +	if (rpdev->announce_destroy)
> +		err = rpdev->announce_destroy(rpdev);
> +
> +	rpdrv->remove(rpdev);
> +
> +	rpmsg_destroy_ept(rpdev->ept);
> +
> +	return err;
> +}
> +
> +static struct bus_type rpmsg_bus = {
> +	.name		= "rpmsg",
> +	.match		= rpmsg_dev_match,
> +	.dev_attrs	= rpmsg_dev_attrs,
> +	.uevent		= rpmsg_uevent,
> +	.probe		= rpmsg_dev_probe,
> +	.remove		= rpmsg_dev_remove,
> +};
> +
> +static void rpmsg_release_device(struct device *dev)
> +{
> +	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> +
> +	kfree(rpdev);
> +}
> +
> +int rpmsg_register_device(struct rpmsg_device *rpdev)
> +{
> +	struct device *dev = &rpdev->dev;
> +	int ret;
> +
> +	dev_set_name(&rpdev->dev, "%s:%s",
> +		     dev_name(dev->parent), rpdev->id.name);
> +
> +	rpdev->dev.bus = &rpmsg_bus;
> +	rpdev->dev.release = rpmsg_release_device;
> +
> +	ret = device_register(&rpdev->dev);
> +	if (ret) {
> +		dev_err(dev, "device_register failed: %d\n", ret);
> +		put_device(&rpdev->dev);
> +	}
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL(rpmsg_register_device);
> +
> +/*
> + * match an rpmsg channel with a channel info struct.
> + * this is used to make sure we're not creating rpmsg devices for channels
> + * that already exist.
> + */
> +static int rpmsg_channel_match(struct device *dev, void *data)
> +{
> +	struct rpmsg_channel_info *chinfo = data;
> +	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> +
> +	if (chinfo->src != RPMSG_ADDR_ANY && chinfo->src != rpdev->src)
> +		return 0;
> +
> +	if (chinfo->dst != RPMSG_ADDR_ANY && chinfo->dst != rpdev->dst)
> +		return 0;
> +
> +	if (strncmp(chinfo->name, rpdev->id.name, RPMSG_NAME_SIZE))
> +		return 0;
> +
> +	/* found a match ! */
> +	return 1;
> +}
> +
> +struct device *rpmsg_find_device(struct device *parent,
> +				 struct rpmsg_channel_info *chinfo)
> +{
> +	return device_find_child(parent, chinfo, rpmsg_channel_match);
> +
> +}
> +EXPORT_SYMBOL(rpmsg_find_device);
> +
> +/*
> + * find an existing channel using its name + address properties,
> + * and destroy it
> + */
> +int rpmsg_unregister_device(struct device *parent,
> +			    struct rpmsg_channel_info *chinfo)
> +{
> +	struct device *dev;
> +
> +	dev = rpmsg_find_device(parent, chinfo);
> +	if (!dev)
> +		return -EINVAL;
> +
> +	device_unregister(dev);
> +
> +	put_device(dev);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(rpmsg_unregister_device);
> +
> +/**
> + * __register_rpmsg_driver() - register an rpmsg driver with the rpmsg bus
> + * @rpdrv: pointer to a struct rpmsg_driver
> + * @owner: owning module/driver
> + *
> + * Returns 0 on success, and an appropriate error value on failure.
> + */
> +int __register_rpmsg_driver(struct rpmsg_driver *rpdrv, struct module
> *owner)
> +{
> +	rpdrv->drv.bus = &rpmsg_bus;
> +	rpdrv->drv.owner = owner;
> +	return driver_register(&rpdrv->drv);
> +}
> +EXPORT_SYMBOL(__register_rpmsg_driver);
> +
> +/**
> + * unregister_rpmsg_driver() - unregister an rpmsg driver from the rpmsg
> bus
> + * @rpdrv: pointer to a struct rpmsg_driver
> + *
> + * Returns 0 on success, and an appropriate error value on failure.
> + */
> +void unregister_rpmsg_driver(struct rpmsg_driver *rpdrv)
> +{
> +	driver_unregister(&rpdrv->drv);
> +}
> +EXPORT_SYMBOL(unregister_rpmsg_driver);
> +
> +
> +static int __init rpmsg_init(void)
> +{
> +	int ret;
> +
> +	ret = bus_register(&rpmsg_bus);
> +	if (ret)
> +		pr_err("failed to register rpmsg bus: %d\n", ret);
> +
> +	return ret;
> +}
> +postcore_initcall(rpmsg_init);
> +
> +static void __exit rpmsg_fini(void)
> +{
> +	bus_unregister(&rpmsg_bus);
> +}
> +module_exit(rpmsg_fini);
> +
> +MODULE_DESCRIPTION("remote processor messaging bus");
> +MODULE_LICENSE("GPL v2");
> diff --git a/drivers/rpmsg/rpmsg_internal.h
> b/drivers/rpmsg/rpmsg_internal.h
> new file mode 100644
> index 000000000000..fa91075c7956
> --- /dev/null
> +++ b/drivers/rpmsg/rpmsg_internal.h
> @@ -0,0 +1,45 @@
> +/*
> + * Virtio-based remote processor messaging bus
> + *
> + * Copyright (C) 2011 Texas Instruments, Inc.
> + * Copyright (C) 2011 Google, Inc.
> + *
> + * Ohad Ben-Cohen <ohad@wizery.com>
> + * Brian Swetland <swetland@google.com>
> + *
> + * This software is licensed under the terms of the GNU General Public
> + * License version 2, as published by the Free Software Foundation, and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __RPMSG_INTERNAL_H__
> +#define __RPMSG_INTERNAL_H__
> +
> +#define to_rpmsg_device(d) container_of(d, struct rpmsg_device, dev)
> +#define to_rpmsg_driver(d) container_of(d, struct rpmsg_driver, drv)
> +
> +/**
> + * struct rpmsg_channel_info - internal channel info representation
> + * @name: name of service
> + * @src: local address
> + * @dst: destination address
> + */
> +struct rpmsg_channel_info {
> +	char name[RPMSG_NAME_SIZE];
> +	u32 src;
> +	u32 dst;
> +};
> +
> +int rpmsg_register_device(struct rpmsg_device *rpdev);
> +int rpmsg_unregister_device(struct device *parent,
> +			    struct rpmsg_channel_info *chinfo);
> +
> +struct device *rpmsg_find_device(struct device *parent,
> +				 struct rpmsg_channel_info *chinfo);
> +
> +#endif
> diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c
> b/drivers/rpmsg/virtio_rpmsg_bus.c
> index 5cadb75a225d..779c54304774 100644
> --- a/drivers/rpmsg/virtio_rpmsg_bus.c
> +++ b/drivers/rpmsg/virtio_rpmsg_bus.c
> @@ -35,6 +35,8 @@
>  #include <linux/mutex.h>
>  #include <linux/of_device.h>
> 
> +#include "rpmsg_internal.h"
> +
>  /**
>   * struct virtproc_info - virtual remote processor state
>   * @vdev:	the virtio device
> @@ -73,21 +75,6 @@ struct virtproc_info {
>  	struct rpmsg_endpoint *ns_ept;
>  };
> 
> -/**
> - * struct rpmsg_channel_info - internal channel info representation
> - * @name: name of service
> - * @src: local address
> - * @dst: destination address
> - */
> -struct rpmsg_channel_info {
> -	char name[RPMSG_NAME_SIZE];
> -	u32 src;
> -	u32 dst;
> -};
> -
> -#define to_rpmsg_device(d) container_of(d, struct rpmsg_device, dev)
> -#define to_rpmsg_driver(d) container_of(d, struct rpmsg_driver, drv)
> -
>  /*
>   * We're allocating buffers of 512 bytes each for communications. The
>   * number of buffers will be computed from the number of buffers
> supported
> @@ -129,72 +116,6 @@ static int virtio_rpmsg_trysendto(struct
> rpmsg_endpoint *ept, void *data,
>  				  int len, u32 dst);
>  static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32
> src,
>  					   u32 dst, void *data, int len);
> -static int rpmsg_register_device(struct rpmsg_device *rpdev);
> -
> -/* sysfs show configuration fields */
> -#define rpmsg_show_attr(field, path, format_string)			\
> -static ssize_t								\
> -field##_show(struct device *dev,					\
> -			struct device_attribute *attr, char *buf)	\
> -{									\
> -	struct rpmsg_device *rpdev = to_rpmsg_device(dev);		\
> -									\
> -	return sprintf(buf, format_string, rpdev->path);		\
> -}
> -
> -/* for more info, see Documentation/ABI/testing/sysfs-bus-rpmsg */
> -rpmsg_show_attr(name, id.name, "%s\n");
> -rpmsg_show_attr(src, src, "0x%x\n");
> -rpmsg_show_attr(dst, dst, "0x%x\n");
> -rpmsg_show_attr(announce, announce ? "true" : "false", "%s\n");
> -
> -static ssize_t modalias_show(struct device *dev,
> -			     struct device_attribute *attr, char *buf)
> -{
> -	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> -
> -	return sprintf(buf, RPMSG_DEVICE_MODALIAS_FMT "\n", rpdev-
> >id.name);
> -}
> -
> -static struct device_attribute rpmsg_dev_attrs[] = {
> -	__ATTR_RO(name),
> -	__ATTR_RO(modalias),
> -	__ATTR_RO(dst),
> -	__ATTR_RO(src),
> -	__ATTR_RO(announce),
> -	__ATTR_NULL
> -};
> -
> -/* rpmsg devices and drivers are matched using the service name */
> -static inline int rpmsg_id_match(const struct rpmsg_device *rpdev,
> -				 const struct rpmsg_device_id *id)
> -{
> -	return strncmp(id->name, rpdev->id.name, RPMSG_NAME_SIZE) ==
> 0;
> -}
> -
> -/* match rpmsg channel and rpmsg driver */
> -static int rpmsg_dev_match(struct device *dev, struct device_driver *drv)
> -{
> -	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> -	struct rpmsg_driver *rpdrv = to_rpmsg_driver(drv);
> -	const struct rpmsg_device_id *ids = rpdrv->id_table;
> -	unsigned int i;
> -
> -	if (ids)
> -		for (i = 0; ids[i].name[0]; i++)
> -			if (rpmsg_id_match(rpdev, &ids[i]))
> -				return 1;
> -
> -	return of_driver_match_device(dev, drv);
> -}
> -
> -static int rpmsg_uevent(struct device *dev, struct kobj_uevent_env *env)
> -{
> -	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> -
> -	return add_uevent_var(env, "MODALIAS="
> RPMSG_DEVICE_MODALIAS_FMT,
> -					rpdev->id.name);
> -}
> 
>  /**
>   * __ept_release() - deallocate an rpmsg endpoint
> @@ -266,53 +187,6 @@ free_ept:
>  	return NULL;
>  }
> 
> -/**
> - * rpmsg_create_ept() - create a new rpmsg_endpoint
> - * @rpdev: rpmsg channel device
> - * @cb: rx callback handler
> - * @priv: private data for the driver's use
> - * @addr: local rpmsg address to bind with @cb
> - *
> - * Every rpmsg address in the system is bound to an rx callback (so when
> - * inbound messages arrive, they are dispatched by the rpmsg bus using the
> - * appropriate callback handler) by means of an rpmsg_endpoint struct.
> - *
> - * This function allows drivers to create such an endpoint, and by that,
> - * bind a callback, and possibly some private data too, to an rpmsg address
> - * (either one that is known in advance, or one that will be dynamically
> - * assigned for them).
> - *
> - * Simple rpmsg drivers need not call rpmsg_create_ept, because an
> endpoint
> - * is already created for them when they are probed by the rpmsg bus
> - * (using the rx callback provided when they registered to the rpmsg bus).
> - *
> - * So things should just work for simple drivers: they already have an
> - * endpoint, their rx callback is bound to their rpmsg address, and when
> - * relevant inbound messages arrive (i.e. messages which their dst address
> - * equals to the src address of their rpmsg channel), the driver's handler
> - * is invoked to process it.
> - *
> - * That said, more complicated drivers might do need to allocate
> - * additional rpmsg addresses, and bind them to different rx callbacks.
> - * To accomplish that, those drivers need to call this function.
> - *
> - * Drivers should provide their @rpdev channel (so the new endpoint would
> belong
> - * to the same remote processor their channel belongs to), an rx callback
> - * function, an optional private data (which is provided back when the
> - * rx callback is invoked), and an address they want to bind with the
> - * callback. If @addr is RPMSG_ADDR_ANY, then rpmsg_create_ept will
> - * dynamically assign them an available rpmsg address (drivers should have
> - * a very good reason why not to always use RPMSG_ADDR_ANY here).
> - *
> - * Returns a pointer to the endpoint on success, or NULL on error.
> - */
> -struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev,
> -					rpmsg_rx_cb_t cb, void *priv, u32
> addr)
> -{
> -	return rpdev->create_ept(rpdev, cb, priv, addr);
> -}
> -EXPORT_SYMBOL(rpmsg_create_ept);
> -
>  static struct rpmsg_endpoint *virtio_rpmsg_create_ept(struct
> rpmsg_device *rpdev,
>  						      rpmsg_rx_cb_t cb,
>  						      void *priv, u32 addr)
> @@ -346,62 +220,11 @@ __rpmsg_destroy_ept(struct virtproc_info *vrp,
> struct rpmsg_endpoint *ept)
>  	kref_put(&ept->refcount, __ept_release);
>  }
> 
> -/**
> - * rpmsg_destroy_ept() - destroy an existing rpmsg endpoint
> - * @ept: endpoing to destroy
> - *
> - * Should be used by drivers to destroy an rpmsg endpoint previously
> - * created with rpmsg_create_ept().
> - */
> -void rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
> -{
> -	ept->rpdev->destroy_ept(ept);
> -}
> -EXPORT_SYMBOL(rpmsg_destroy_ept);
> -
>  static void virtio_rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
>  {
>  	__rpmsg_destroy_ept(ept->rpdev->vrp, ept);
>  }
> 
> -/*
> - * when an rpmsg driver is probed with a channel, we seamlessly create
> - * it an endpoint, binding its rx callback to a unique local rpmsg
> - * address.
> - *
> - * if we need to, we also announce about this channel to the remote
> - * processor (needed in case the driver is exposing an rpmsg service).
> - */
> -static int rpmsg_dev_probe(struct device *dev)
> -{
> -	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> -	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
> -	struct rpmsg_endpoint *ept;
> -	int err;
> -
> -	ept = rpmsg_create_ept(rpdev, rpdrv->callback, NULL, rpdev->src);
> -	if (!ept) {
> -		dev_err(dev, "failed to create endpoint\n");
> -		err = -ENOMEM;
> -		goto out;
> -	}
> -
> -	rpdev->ept = ept;
> -	rpdev->src = ept->addr;
> -
> -	err = rpdrv->probe(rpdev);
> -	if (err) {
> -		dev_err(dev, "%s: failed: %d\n", __func__, err);
> -		rpmsg_destroy_ept(ept);
> -		goto out;
> -	}
> -
> -	if (rpdev->announce_create)
> -		err = rpdev->announce_create(rpdev);
> -out:
> -	return err;
> -}
> -
>  static int virtio_rpmsg_announce_create(struct rpmsg_device *rpdev)
>  {
>  	struct virtproc_info *vrp = rpdev->vrp;
> @@ -448,88 +271,6 @@ static int virtio_rpmsg_announce_destroy(struct
> rpmsg_device *rpdev)
>  	return err;
>  }
> 
> -static int rpmsg_dev_remove(struct device *dev)
> -{
> -	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> -	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
> -	int err = 0;
> -
> -	if (rpdev->announce_destroy)
> -		err = rpdev->announce_destroy(rpdev);
> -
> -	rpdrv->remove(rpdev);
> -
> -	rpmsg_destroy_ept(rpdev->ept);
> -
> -	return err;
> -}
> -
> -static struct bus_type rpmsg_bus = {
> -	.name		= "rpmsg",
> -	.match		= rpmsg_dev_match,
> -	.dev_attrs	= rpmsg_dev_attrs,
> -	.uevent		= rpmsg_uevent,
> -	.probe		= rpmsg_dev_probe,
> -	.remove		= rpmsg_dev_remove,
> -};
> -
> -/**
> - * __register_rpmsg_driver() - register an rpmsg driver with the rpmsg bus
> - * @rpdrv: pointer to a struct rpmsg_driver
> - * @owner: owning module/driver
> - *
> - * Returns 0 on success, and an appropriate error value on failure.
> - */
> -int __register_rpmsg_driver(struct rpmsg_driver *rpdrv, struct module
> *owner)
> -{
> -	rpdrv->drv.bus = &rpmsg_bus;
> -	rpdrv->drv.owner = owner;
> -	return driver_register(&rpdrv->drv);
> -}
> -EXPORT_SYMBOL(__register_rpmsg_driver);
> -
> -/**
> - * unregister_rpmsg_driver() - unregister an rpmsg driver from the rpmsg
> bus
> - * @rpdrv: pointer to a struct rpmsg_driver
> - *
> - * Returns 0 on success, and an appropriate error value on failure.
> - */
> -void unregister_rpmsg_driver(struct rpmsg_driver *rpdrv)
> -{
> -	driver_unregister(&rpdrv->drv);
> -}
> -EXPORT_SYMBOL(unregister_rpmsg_driver);
> -
> -static void rpmsg_release_device(struct device *dev)
> -{
> -	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> -
> -	kfree(rpdev);
> -}
> -
> -/*
> - * match an rpmsg channel with a channel info struct.
> - * this is used to make sure we're not creating rpmsg devices for channels
> - * that already exist.
> - */
> -static int rpmsg_device_match(struct device *dev, void *data)
> -{
> -	struct rpmsg_channel_info *chinfo = data;
> -	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> -
> -	if (chinfo->src != RPMSG_ADDR_ANY && chinfo->src != rpdev->src)
> -		return 0;
> -
> -	if (chinfo->dst != RPMSG_ADDR_ANY && chinfo->dst != rpdev->dst)
> -		return 0;
> -
> -	if (strncmp(chinfo->name, rpdev->id.name, RPMSG_NAME_SIZE))
> -		return 0;
> -
> -	/* found a match ! */
> -	return 1;
> -}
> -
>  static const struct rpmsg_device virtio_rpmsg_ops = {
>  	.create_ept = virtio_rpmsg_create_ept,
>  	.destroy_ept = virtio_rpmsg_destroy_ept,
> @@ -556,7 +297,7 @@ static struct rpmsg_device
> *rpmsg_create_channel(struct virtproc_info *vrp,
>  	int ret;
> 
>  	/* make sure a similar channel doesn't already exist */
> -	tmp = device_find_child(dev, chinfo, rpmsg_device_match);
> +	tmp = rpmsg_find_device(dev, chinfo);
>  	if (tmp) {
>  		/* decrement the matched device's refcount back */
>  		put_device(tmp);
> @@ -592,47 +333,6 @@ static struct rpmsg_device
> *rpmsg_create_channel(struct virtproc_info *vrp,
>  	return rpdev;
>  }
> 
> -static int rpmsg_register_device(struct rpmsg_device *rpdev)
> -{
> -	struct device *dev = &rpdev->dev;
> -	int ret;
> -
> -	dev_set_name(&rpdev->dev, "%s:%s",
> -		     dev_name(dev->parent), rpdev->id.name);
> -
> -	rpdev->dev.bus = &rpmsg_bus;
> -	rpdev->dev.release = rpmsg_release_device;
> -
> -	ret = device_register(&rpdev->dev);
> -	if (ret) {
> -		dev_err(dev, "device_register failed: %d\n", ret);
> -		put_device(&rpdev->dev);
> -	}
> -
> -	return ret;
> -}
> -
> -/*
> - * find an existing channel using its name + address properties,
> - * and destroy it
> - */
> -static int rpmsg_destroy_channel(struct virtproc_info *vrp,
> -				 struct rpmsg_channel_info *chinfo)
> -{
> -	struct virtio_device *vdev = vrp->vdev;
> -	struct device *dev;
> -
> -	dev = device_find_child(&vdev->dev, chinfo, rpmsg_device_match);
> -	if (!dev)
> -		return -EINVAL;
> -
> -	device_unregister(dev);
> -
> -	put_device(dev);
> -
> -	return 0;
> -}
> -
>  /* super simple buffer "allocator" that is just enough for now */
>  static void *get_a_tx_buf(struct virtproc_info *vrp)
>  {
> @@ -844,31 +544,6 @@ out:
>  	return err;
>  }
> 
> -/**
> - * rpmsg_send() - send a message across to the remote processor
> - * @ept: the rpmsg endpoint
> - * @data: payload of message
> - * @len: length of payload
> - *
> - * This function sends @data of length @len on the @ept endpoint.
> - * The message will be sent to the remote processor which the @ept
> - * endpoint belongs to, using @ept's address and its associated rpmsg
> - * device destination addresses.
> - * In case there are no TX buffers available, the function will block until
> - * one becomes available, or a timeout of 15 seconds elapses. When the
> latter
> - * happens, -ERESTARTSYS is returned.
> - *
> - * Can only be called from process context (for now).
> - *
> - * Returns 0 on success and an appropriate error value on failure.
> - */
> -int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
> -{
> -	struct rpmsg_device *rpdev = ept->rpdev;
> -
> -	return rpdev->send(ept, data, len);
> -}
> -
>  static int virtio_rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
>  {
>  	struct rpmsg_device *rpdev = ept->rpdev;
> @@ -877,32 +552,6 @@ static int virtio_rpmsg_send(struct rpmsg_endpoint
> *ept, void *data, int len)
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
>  }
> 
> -/**
> - * rpmsg_sendto() - send a message across to the remote processor, specify
> dst
> - * @ept: the rpmsg endpoint
> - * @data: payload of message
> - * @len: length of payload
> - * @dst: destination address
> - *
> - * This function sends @data of length @len to the remote @dst address.
> - * The message will be sent to the remote processor which the @ept
> - * endpoint belongs to, using @ept's address as source.
> - * In case there are no TX buffers available, the function will block until
> - * one becomes available, or a timeout of 15 seconds elapses. When the
> latter
> - * happens, -ERESTARTSYS is returned.
> - *
> - * Can only be called from process context (for now).
> - *
> - * Returns 0 on success and an appropriate error value on failure.
> - */
> -int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
> -{
> -	struct rpmsg_device *rpdev = ept->rpdev;
> -
> -	return rpdev->sendto(ept, data, len, dst);
> -}
> -EXPORT_SYMBOL(rpmsg_sendto);
> -
>  static int virtio_rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int
> len,
>  			       u32 dst)
>  {
> @@ -912,35 +561,6 @@ static int virtio_rpmsg_sendto(struct
> rpmsg_endpoint *ept, void *data, int len,
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
>  }
> 
> -/**
> - * rpmsg_send_offchannel() - send a message using explicit src/dst
> addresses
> - * @ept: the rpmsg endpoint
> - * @src: source address
> - * @dst: destination address
> - * @data: payload of message
> - * @len: length of payload
> - *
> - * This function sends @data of length @len to the remote @dst address,
> - * and uses @src as the source address.
> - * The message will be sent to the remote processor which the @ept
> - * endpoint belongs to.
> - * In case there are no TX buffers available, the function will block until
> - * one becomes available, or a timeout of 15 seconds elapses. When the
> latter
> - * happens, -ERESTARTSYS is returned.
> - *
> - * Can only be called from process context (for now).
> - *
> - * Returns 0 on success and an appropriate error value on failure.
> - */
> -int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
> -			  void *data, int len)
> -{
> -	struct rpmsg_device *rpdev = ept->rpdev;
> -
> -	return rpdev->send_offchannel(ept, src, dst, data, len);
> -}
> -EXPORT_SYMBOL(rpmsg_send_offchannel);
> -
>  static int virtio_rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32
> src,
>  					u32 dst, void *data, int len)
>  {
> @@ -949,31 +569,6 @@ static int virtio_rpmsg_send_offchannel(struct
> rpmsg_endpoint *ept, u32 src,
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
>  }
> 
> -/**
> - * rpmsg_send() - send a message across to the remote processor
> - * @ept: the rpmsg endpoint
> - * @data: payload of message
> - * @len: length of payload
> - *
> - * This function sends @data of length @len on the @ept endpoint.
> - * The message will be sent to the remote processor which the @ept
> - * endpoint belongs to, using @ept's addres as source and its associated
> - * rpdev's address as destination.
> - * In case there are no TX buffers available, the function will immediately
> - * return -ENOMEM without waiting until one becomes available.
> - *
> - * Can only be called from process context (for now).
> - *
> - * Returns 0 on success and an appropriate error value on failure.
> - */
> -int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
> -{
> -	struct rpmsg_device *rpdev = ept->rpdev;
> -
> -	return rpdev->trysend(ept, data, len);
> -}
> -EXPORT_SYMBOL(rpmsg_trysend);
> -
>  static int virtio_rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int
> len)
>  {
>  	struct rpmsg_device *rpdev = ept->rpdev;
> @@ -982,31 +577,6 @@ static int virtio_rpmsg_trysend(struct
> rpmsg_endpoint *ept, void *data, int len)
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
>  }
> 
> -/**
> - * rpmsg_sendto() - send a message across to the remote processor, specify
> dst
> - * @ept: the rpmsg endpoint
> - * @data: payload of message
> - * @len: length of payload
> - * @dst: destination address
> - *
> - * This function sends @data of length @len to the remote @dst address.
> - * The message will be sent to the remote processor which the @ept
> - * endpoint belongs to, using @ept's address as source.
> - * In case there are no TX buffers available, the function will immediately
> - * return -ENOMEM without waiting until one becomes available.
> - *
> - * Can only be called from process context (for now).
> - *
> - * Returns 0 on success and an appropriate error value on failure.
> - */
> -int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32
> dst)
> -{
> -	struct rpmsg_device *rpdev = ept->rpdev;
> -
> -	return rpdev->trysendto(ept, data, len, dst);
> -}
> -EXPORT_SYMBOL(rpmsg_trysendto);
> -
>  static int virtio_rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data,
>  				  int len, u32 dst)
>  {
> @@ -1016,34 +586,6 @@ static int virtio_rpmsg_trysendto(struct
> rpmsg_endpoint *ept, void *data,
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
>  }
> 
> -/**
> - * rpmsg_send_offchannel() - send a message using explicit src/dst
> addresses
> - * @ept: the rpmsg endpoint
> - * @src: source address
> - * @dst: destination address
> - * @data: payload of message
> - * @len: length of payload
> - *
> - * This function sends @data of length @len to the remote @dst address,
> - * and uses @src as the source address.
> - * The message will be sent to the remote processor which the @ept
> - * endpoint belongs to.
> - * In case there are no TX buffers available, the function will immediately
> - * return -ENOMEM without waiting until one becomes available.
> - *
> - * Can only be called from process context (for now).
> - *
> - * Returns 0 on success and an appropriate error value on failure.
> - */
> -int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32
> dst,
> -			     void *data, int len)
> -{
> -	struct rpmsg_device *rpdev = ept->rpdev;
> -
> -	return rpdev->trysend_offchannel(ept, src, dst, data, len);
> -}
> -EXPORT_SYMBOL(rpmsg_trysend_offchannel);
> -
>  static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32
> src,
>  					   u32 dst, void *data, int len)
>  {
> @@ -1208,7 +750,7 @@ static void rpmsg_ns_cb(struct rpmsg_device
> *rpdev, void *data, int len,
>  	chinfo.dst = msg->addr;
> 
>  	if (msg->flags & RPMSG_NS_DESTROY) {
> -		ret = rpmsg_destroy_channel(vrp, &chinfo);
> +		ret = rpmsg_unregister_device(&vrp->vdev->dev, &chinfo);
>  		if (ret)
>  			dev_err(dev, "rpmsg_destroy_channel failed: %d\n",
> ret);
>  	} else {
> @@ -1393,17 +935,9 @@ static int __init rpmsg_init(void)
>  {
>  	int ret;
> 
> -	ret = bus_register(&rpmsg_bus);
> -	if (ret) {
> -		pr_err("failed to register rpmsg bus: %d\n", ret);
> -		return ret;
> -	}
> -
>  	ret = register_virtio_driver(&virtio_ipc_driver);
> -	if (ret) {
> +	if (ret)
>  		pr_err("failed to register virtio driver: %d\n", ret);
> -		bus_unregister(&rpmsg_bus);
> -	}
> 
>  	return ret;
>  }
> @@ -1412,7 +946,6 @@ subsys_initcall(rpmsg_init);
>  static void __exit rpmsg_fini(void)
>  {
>  	unregister_virtio_driver(&virtio_ipc_driver);
> -	bus_unregister(&rpmsg_bus);
>  }
>  module_exit(rpmsg_fini);
> 
> --
> 2.5.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-remoteproc" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 54+ messages in thread

* RE: [PATCH 06/14] rpmsg: Indirect all virtio related function calls
  2016-08-16  0:17   ` Bjorn Andersson
  (?)
@ 2016-08-18 12:14     ` Loic PALLARDY
  -1 siblings, 0 replies; 54+ messages in thread
From: Loic PALLARDY @ 2016-08-18 12:14 UTC (permalink / raw)
  To: Bjorn Andersson, Ohad Ben-Cohen
  Cc: linux-remoteproc, linux-arm-msm, linux-arm-kernel, linux-kernel



> -----Original Message-----
> From: linux-remoteproc-owner@vger.kernel.org [mailto:linux-remoteproc-
> owner@vger.kernel.org] On Behalf Of Bjorn Andersson
> Sent: Tuesday, August 16, 2016 2:17 AM
> To: Ohad Ben-Cohen <ohad@wizery.com>; Bjorn Andersson
> <bjorn.andersson@linaro.org>
> Cc: linux-remoteproc@vger.kernel.org; linux-arm-msm@vger.kernel.org;
> linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org
> Subject: [PATCH 06/14] rpmsg: Indirect all virtio related function calls
> 
> Create indirections for functions in prepration for splitting the rpmsg
> core functionality from the virtio backend.
> 
> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> ---
>  drivers/rpmsg/virtio_rpmsg_bus.c | 131
> +++++++++++++++++++++++++++++++++++----
>  include/linux/rpmsg.h            |  23 ++++++-
>  2 files changed, 139 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c
> b/drivers/rpmsg/virtio_rpmsg_bus.c
> index a9f8cc8d968b..1dc7a1149c51 100644
> --- a/drivers/rpmsg/virtio_rpmsg_bus.c
> +++ b/drivers/rpmsg/virtio_rpmsg_bus.c
> @@ -119,6 +119,17 @@ struct rpmsg_channel_info {
>  /* Address 53 is reserved for advertising remote services */
>  #define RPMSG_NS_ADDR			(53)
> 
> +static int virtio_rpmsg_send(struct rpmsg_endpoint *ept, void *data, int
> len);
> +static int virtio_rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int
> len,
> +			       u32 dst);
> +static int virtio_rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32
> src,
> +					u32 dst, void *data, int len);
> +static int virtio_rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int
> len);
> +static int virtio_rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data,
> +				  int len, u32 dst);
> +static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept,
> u32 src,
> +					   u32 dst, void *data, int len);
> +
>  /* sysfs show configuration fields */
>  #define rpmsg_show_attr(field, path, format_string)			\
>  static ssize_t								\
> @@ -297,10 +308,17 @@ free_ept:
>  struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev,
>  					rpmsg_rx_cb_t cb, void *priv, u32
> addr)
>  {
> -	return __rpmsg_create_ept(rpdev->vrp, rpdev, cb, priv, addr);
> +	return rpdev->create_ept(rpdev, cb, priv, addr);
Hi Bjorn,

It will be good to test if pointer is valid before calling function.

>  }
>  EXPORT_SYMBOL(rpmsg_create_ept);
> 
> +static struct rpmsg_endpoint *virtio_rpmsg_create_ept(struct
> rpmsg_device *rpdev,
> +						      rpmsg_rx_cb_t cb,
> +						      void *priv, u32 addr)
> +{
> +	return __rpmsg_create_ept(rpdev->vrp, rpdev, cb, priv, addr);
> +}
> +
>  /**
>   * __rpmsg_destroy_ept() - destroy an existing rpmsg endpoint
>   * @vrp: virtproc which owns this ept
> @@ -336,10 +354,15 @@ __rpmsg_destroy_ept(struct virtproc_info *vrp,
> struct rpmsg_endpoint *ept)
>   */
>  void rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
>  {
> -	__rpmsg_destroy_ept(ept->rpdev->vrp, ept);
> +	ept->rpdev->destroy_ept(ept);
Ditto

>  }
>  EXPORT_SYMBOL(rpmsg_destroy_ept);
> 
> +static void virtio_rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
> +{
> +	__rpmsg_destroy_ept(ept->rpdev->vrp, ept);
> +}
> +
>  /*
>   * when an rpmsg driver is probed with a channel, we seamlessly create
>   * it an endpoint, binding its rx callback to a unique local rpmsg
> @@ -352,7 +375,6 @@ static int rpmsg_dev_probe(struct device *dev)
>  {
>  	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
>  	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
> -	struct virtproc_info *vrp = rpdev->vrp;
>  	struct rpmsg_endpoint *ept;
>  	int err;
> 
> @@ -373,6 +395,18 @@ static int rpmsg_dev_probe(struct device *dev)
>  		goto out;
>  	}
> 
> +	if (rpdev->announce_create)
> +		err = rpdev->announce_create(rpdev);
> +out:
> +	return err;
> +}
> +
> +static int virtio_rpmsg_announce_create(struct rpmsg_device *rpdev)
> +{
> +	struct virtproc_info *vrp = rpdev->vrp;
> +	struct device *dev = &rpdev->dev;
> +	int err = 0;
> +
>  	/* need to tell remote processor's name service about this channel ?
> */
>  	if (rpdev->announce &&
>  	    virtio_has_feature(vrp->vdev, VIRTIO_RPMSG_F_NS)) {
> @@ -387,15 +421,13 @@ static int rpmsg_dev_probe(struct device *dev)
>  			dev_err(dev, "failed to announce service %d\n", err);
>  	}
> 
> -out:
>  	return err;
>  }
> 
> -static int rpmsg_dev_remove(struct device *dev)
> +static int virtio_rpmsg_announce_destroy(struct rpmsg_device *rpdev)
>  {
> -	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> -	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
>  	struct virtproc_info *vrp = rpdev->vrp;
> +	struct device *dev = &rpdev->dev;
>  	int err = 0;
> 
>  	/* tell remote processor's name service we're removing this channel
> */
> @@ -412,6 +444,18 @@ static int rpmsg_dev_remove(struct device *dev)
>  			dev_err(dev, "failed to announce service %d\n", err);
>  	}
> 
> +	return err;
> +}
> +
> +static int rpmsg_dev_remove(struct device *dev)
> +{
> +	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> +	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
> +	int err = 0;
> +
> +	if (rpdev->announce_destroy)
> +		err = rpdev->announce_destroy(rpdev);
> +
>  	rpdrv->remove(rpdev);
> 
>  	rpmsg_destroy_ept(rpdev->ept);
> @@ -485,6 +529,19 @@ static int rpmsg_device_match(struct device *dev,
> void *data)
>  	return 1;
>  }
> 
> +static const struct rpmsg_device virtio_rpmsg_ops = {
> +	.create_ept = virtio_rpmsg_create_ept,
> +	.destroy_ept = virtio_rpmsg_destroy_ept,
> +	.send = virtio_rpmsg_send,
> +	.sendto = virtio_rpmsg_sendto,
> +	.send_offchannel = virtio_rpmsg_send_offchannel,
> +	.trysend = virtio_rpmsg_trysend,
> +	.trysendto = virtio_rpmsg_trysendto,
> +	.trysend_offchannel = virtio_rpmsg_trysend_offchannel,
> +	.announce_create = virtio_rpmsg_announce_create,
> +	.announce_destroy = virtio_rpmsg_announce_destroy,
> +};
Why not creating a dedicated ops struct like other framework?
Here ops are mixed with other parameters.

> +
>  /*
>   * create an rpmsg channel using its name and address info.
>   * this function will be used to create both static and dynamic
> @@ -511,6 +568,9 @@ static struct rpmsg_device
> *rpmsg_create_channel(struct virtproc_info *vrp,
>  	if (!rpdev)
>  		return NULL;
> 
> +	/* Assign callbacks for rpmsg_channel */
> +	*rpdev = virtio_rpmsg_ops;
It is not a simple affectation behind this operation, more a memcopy of the complete struct.
Not easy to read from my pov.
> +
>  	rpdev->vrp = vrp;
>  	rpdev->src = chinfo->src;
>  	rpdev->dst = chinfo->dst;
> @@ -793,11 +853,17 @@ out:
>  int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
>  {
>  	struct rpmsg_device *rpdev = ept->rpdev;
> +
> +	return rpdev->send(ept, data, len);
Test pointer before using it

> +}
> +
> +static int virtio_rpmsg_send(struct rpmsg_endpoint *ept, void *data, int
> len)
> +{
> +	struct rpmsg_device *rpdev = ept->rpdev;
>  	u32 src = ept->addr, dst = rpdev->dst;
> 
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
>  }
> -EXPORT_SYMBOL(rpmsg_send);
> 
>  /**
>   * rpmsg_sendto() - send a message across to the remote processor, specify
> dst
> @@ -820,11 +886,19 @@ EXPORT_SYMBOL(rpmsg_send);
>  int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
>  {
>  	struct rpmsg_device *rpdev = ept->rpdev;
> +
> +	return rpdev->sendto(ept, data, len, dst);
Ditto

> +}
> +EXPORT_SYMBOL(rpmsg_sendto);
> +
> +static int virtio_rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int
> len,
> +			       u32 dst)
> +{
> +	struct rpmsg_device *rpdev = ept->rpdev;
>  	u32 src = ept->addr;
> 
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
>  }
> -EXPORT_SYMBOL(rpmsg_sendto);
> 
>  /**
>   * rpmsg_send_offchannel() - send a message using explicit src/dst
> addresses
> @@ -851,10 +925,18 @@ int rpmsg_send_offchannel(struct rpmsg_endpoint
> *ept, u32 src, u32 dst,
>  {
>  	struct rpmsg_device *rpdev = ept->rpdev;
> 
> -	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
> +	return rpdev->send_offchannel(ept, src, dst, data, len);
>  }
>  EXPORT_SYMBOL(rpmsg_send_offchannel);
> 
> +static int virtio_rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32
> src,
> +					u32 dst, void *data, int len)
> +{
> +	struct rpmsg_device *rpdev = ept->rpdev;
> +
> +	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
> +}
> +
>  /**
>   * rpmsg_send() - send a message across to the remote processor
>   * @ept: the rpmsg endpoint
> @@ -875,11 +957,18 @@ EXPORT_SYMBOL(rpmsg_send_offchannel);
>  int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
>  {
>  	struct rpmsg_device *rpdev = ept->rpdev;
> +
> +	return rpdev->trysend(ept, data, len);
ditto
> +}
> +EXPORT_SYMBOL(rpmsg_trysend);
> +
> +static int virtio_rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int
> len)
> +{
> +	struct rpmsg_device *rpdev = ept->rpdev;
>  	u32 src = ept->addr, dst = rpdev->dst;
> 
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
>  }
> -EXPORT_SYMBOL(rpmsg_trysend);
> 
>  /**
>   * rpmsg_sendto() - send a message across to the remote processor, specify
> dst
> @@ -901,11 +990,19 @@ EXPORT_SYMBOL(rpmsg_trysend);
>  int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32
> dst)
>  {
>  	struct rpmsg_device *rpdev = ept->rpdev;
> +
> +	return rpdev->trysendto(ept, data, len, dst);
ditto
> +}
> +EXPORT_SYMBOL(rpmsg_trysendto);
> +
> +static int virtio_rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data,
> +				  int len, u32 dst)
> +{
> +	struct rpmsg_device *rpdev = ept->rpdev;
>  	u32 src = ept->addr;
> 
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
>  }
> -EXPORT_SYMBOL(rpmsg_trysendto);
> 
>  /**
>   * rpmsg_send_offchannel() - send a message using explicit src/dst
> addresses
> @@ -931,10 +1028,18 @@ int rpmsg_trysend_offchannel(struct
> rpmsg_endpoint *ept, u32 src, u32 dst,
>  {
>  	struct rpmsg_device *rpdev = ept->rpdev;
> 
> -	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
> +	return rpdev->trysend_offchannel(ept, src, dst, data, len);
ditto
>  }
>  EXPORT_SYMBOL(rpmsg_trysend_offchannel);
> 
> +static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept,
> u32 src,
> +					   u32 dst, void *data, int len)
> +{
> +	struct rpmsg_device *rpdev = ept->rpdev;
> +
> +	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
> +}
> +
>  static int rpmsg_recv_single(struct virtproc_info *vrp, struct device *dev,
>  			     struct rpmsg_hdr *msg, unsigned int len)
>  {
> diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
> index 3e3d5b1c154a..0b290ae18e70 100644
> --- a/include/linux/rpmsg.h
> +++ b/include/linux/rpmsg.h
> @@ -96,6 +96,10 @@ enum rpmsg_ns_flags {
>  #define RPMSG_ADDR_ANY		0xFFFFFFFF
> 
>  struct virtproc_info;
> +struct rpmsg_device;
> +struct rpmsg_endpoint;
> +
> +typedef void (*rpmsg_rx_cb_t)(struct rpmsg_device *, void *, int, void *,
> u32);
> 
>  /**
>   * rpmsg_device - device that belong to the rpmsg bus
> @@ -115,9 +119,24 @@ struct rpmsg_device {
>  	u32 dst;
>  	struct rpmsg_endpoint *ept;
>  	bool announce;
> -};
> 
> -typedef void (*rpmsg_rx_cb_t)(struct rpmsg_device *, void *, int, void *,
> u32);
> +	struct rpmsg_endpoint *(*create_ept)(struct rpmsg_device *rpdev,
> +					    rpmsg_rx_cb_t cb, void *priv, u32
> addr);
> +	void (*destroy_ept)(struct rpmsg_endpoint *ept);
> +
> +	int (*send)(struct rpmsg_endpoint *ept, void *data, int len);
> +	int (*sendto)(struct rpmsg_endpoint *ept, void *data, int len, u32
> dst);
> +	int (*send_offchannel)(struct rpmsg_endpoint *ept, u32 src, u32 dst,
> +				  void *data, int len);
> +
> +	int (*trysend)(struct rpmsg_endpoint *ept, void *data, int len);
> +	int (*trysendto)(struct rpmsg_endpoint *ept, void *data, int len, u32
> dst);
> +	int (*trysend_offchannel)(struct rpmsg_endpoint *ept, u32 src, u32
> dst,
> +			     void *data, int len);
> +
> +	int (*announce_create)(struct rpmsg_device *ept);
> +	int (*announce_destroy)(struct rpmsg_device *ept);
> +};
It will be nice to document if ops are mandatory or optional.

Regards,
Loic
> 
>  /**
>   * struct rpmsg_endpoint - binds a local rpmsg address to its user
> --
> 2.5.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-remoteproc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 54+ messages in thread

* RE: [PATCH 06/14] rpmsg: Indirect all virtio related function calls
@ 2016-08-18 12:14     ` Loic PALLARDY
  0 siblings, 0 replies; 54+ messages in thread
From: Loic PALLARDY @ 2016-08-18 12:14 UTC (permalink / raw)
  To: Bjorn Andersson, Ohad Ben-Cohen
  Cc: linux-remoteproc, linux-arm-msm, linux-arm-kernel, linux-kernel



> -----Original Message-----
> From: linux-remoteproc-owner@vger.kernel.org [mailto:linux-remoteproc-
> owner@vger.kernel.org] On Behalf Of Bjorn Andersson
> Sent: Tuesday, August 16, 2016 2:17 AM
> To: Ohad Ben-Cohen <ohad@wizery.com>; Bjorn Andersson
> <bjorn.andersson@linaro.org>
> Cc: linux-remoteproc@vger.kernel.org; linux-arm-msm@vger.kernel.org;
> linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org
> Subject: [PATCH 06/14] rpmsg: Indirect all virtio related function calls
> 
> Create indirections for functions in prepration for splitting the rpmsg
> core functionality from the virtio backend.
> 
> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> ---
>  drivers/rpmsg/virtio_rpmsg_bus.c | 131
> +++++++++++++++++++++++++++++++++++----
>  include/linux/rpmsg.h            |  23 ++++++-
>  2 files changed, 139 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c
> b/drivers/rpmsg/virtio_rpmsg_bus.c
> index a9f8cc8d968b..1dc7a1149c51 100644
> --- a/drivers/rpmsg/virtio_rpmsg_bus.c
> +++ b/drivers/rpmsg/virtio_rpmsg_bus.c
> @@ -119,6 +119,17 @@ struct rpmsg_channel_info {
>  /* Address 53 is reserved for advertising remote services */
>  #define RPMSG_NS_ADDR			(53)
> 
> +static int virtio_rpmsg_send(struct rpmsg_endpoint *ept, void *data, int
> len);
> +static int virtio_rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int
> len,
> +			       u32 dst);
> +static int virtio_rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32
> src,
> +					u32 dst, void *data, int len);
> +static int virtio_rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int
> len);
> +static int virtio_rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data,
> +				  int len, u32 dst);
> +static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept,
> u32 src,
> +					   u32 dst, void *data, int len);
> +
>  /* sysfs show configuration fields */
>  #define rpmsg_show_attr(field, path, format_string)			\
>  static ssize_t								\
> @@ -297,10 +308,17 @@ free_ept:
>  struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev,
>  					rpmsg_rx_cb_t cb, void *priv, u32
> addr)
>  {
> -	return __rpmsg_create_ept(rpdev->vrp, rpdev, cb, priv, addr);
> +	return rpdev->create_ept(rpdev, cb, priv, addr);
Hi Bjorn,

It will be good to test if pointer is valid before calling function.

>  }
>  EXPORT_SYMBOL(rpmsg_create_ept);
> 
> +static struct rpmsg_endpoint *virtio_rpmsg_create_ept(struct
> rpmsg_device *rpdev,
> +						      rpmsg_rx_cb_t cb,
> +						      void *priv, u32 addr)
> +{
> +	return __rpmsg_create_ept(rpdev->vrp, rpdev, cb, priv, addr);
> +}
> +
>  /**
>   * __rpmsg_destroy_ept() - destroy an existing rpmsg endpoint
>   * @vrp: virtproc which owns this ept
> @@ -336,10 +354,15 @@ __rpmsg_destroy_ept(struct virtproc_info *vrp,
> struct rpmsg_endpoint *ept)
>   */
>  void rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
>  {
> -	__rpmsg_destroy_ept(ept->rpdev->vrp, ept);
> +	ept->rpdev->destroy_ept(ept);
Ditto

>  }
>  EXPORT_SYMBOL(rpmsg_destroy_ept);
> 
> +static void virtio_rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
> +{
> +	__rpmsg_destroy_ept(ept->rpdev->vrp, ept);
> +}
> +
>  /*
>   * when an rpmsg driver is probed with a channel, we seamlessly create
>   * it an endpoint, binding its rx callback to a unique local rpmsg
> @@ -352,7 +375,6 @@ static int rpmsg_dev_probe(struct device *dev)
>  {
>  	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
>  	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
> -	struct virtproc_info *vrp = rpdev->vrp;
>  	struct rpmsg_endpoint *ept;
>  	int err;
> 
> @@ -373,6 +395,18 @@ static int rpmsg_dev_probe(struct device *dev)
>  		goto out;
>  	}
> 
> +	if (rpdev->announce_create)
> +		err = rpdev->announce_create(rpdev);
> +out:
> +	return err;
> +}
> +
> +static int virtio_rpmsg_announce_create(struct rpmsg_device *rpdev)
> +{
> +	struct virtproc_info *vrp = rpdev->vrp;
> +	struct device *dev = &rpdev->dev;
> +	int err = 0;
> +
>  	/* need to tell remote processor's name service about this channel ?
> */
>  	if (rpdev->announce &&
>  	    virtio_has_feature(vrp->vdev, VIRTIO_RPMSG_F_NS)) {
> @@ -387,15 +421,13 @@ static int rpmsg_dev_probe(struct device *dev)
>  			dev_err(dev, "failed to announce service %d\n", err);
>  	}
> 
> -out:
>  	return err;
>  }
> 
> -static int rpmsg_dev_remove(struct device *dev)
> +static int virtio_rpmsg_announce_destroy(struct rpmsg_device *rpdev)
>  {
> -	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> -	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
>  	struct virtproc_info *vrp = rpdev->vrp;
> +	struct device *dev = &rpdev->dev;
>  	int err = 0;
> 
>  	/* tell remote processor's name service we're removing this channel
> */
> @@ -412,6 +444,18 @@ static int rpmsg_dev_remove(struct device *dev)
>  			dev_err(dev, "failed to announce service %d\n", err);
>  	}
> 
> +	return err;
> +}
> +
> +static int rpmsg_dev_remove(struct device *dev)
> +{
> +	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> +	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
> +	int err = 0;
> +
> +	if (rpdev->announce_destroy)
> +		err = rpdev->announce_destroy(rpdev);
> +
>  	rpdrv->remove(rpdev);
> 
>  	rpmsg_destroy_ept(rpdev->ept);
> @@ -485,6 +529,19 @@ static int rpmsg_device_match(struct device *dev,
> void *data)
>  	return 1;
>  }
> 
> +static const struct rpmsg_device virtio_rpmsg_ops = {
> +	.create_ept = virtio_rpmsg_create_ept,
> +	.destroy_ept = virtio_rpmsg_destroy_ept,
> +	.send = virtio_rpmsg_send,
> +	.sendto = virtio_rpmsg_sendto,
> +	.send_offchannel = virtio_rpmsg_send_offchannel,
> +	.trysend = virtio_rpmsg_trysend,
> +	.trysendto = virtio_rpmsg_trysendto,
> +	.trysend_offchannel = virtio_rpmsg_trysend_offchannel,
> +	.announce_create = virtio_rpmsg_announce_create,
> +	.announce_destroy = virtio_rpmsg_announce_destroy,
> +};
Why not creating a dedicated ops struct like other framework?
Here ops are mixed with other parameters.

> +
>  /*
>   * create an rpmsg channel using its name and address info.
>   * this function will be used to create both static and dynamic
> @@ -511,6 +568,9 @@ static struct rpmsg_device
> *rpmsg_create_channel(struct virtproc_info *vrp,
>  	if (!rpdev)
>  		return NULL;
> 
> +	/* Assign callbacks for rpmsg_channel */
> +	*rpdev = virtio_rpmsg_ops;
It is not a simple affectation behind this operation, more a memcopy of the complete struct.
Not easy to read from my pov.
> +
>  	rpdev->vrp = vrp;
>  	rpdev->src = chinfo->src;
>  	rpdev->dst = chinfo->dst;
> @@ -793,11 +853,17 @@ out:
>  int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
>  {
>  	struct rpmsg_device *rpdev = ept->rpdev;
> +
> +	return rpdev->send(ept, data, len);
Test pointer before using it

> +}
> +
> +static int virtio_rpmsg_send(struct rpmsg_endpoint *ept, void *data, int
> len)
> +{
> +	struct rpmsg_device *rpdev = ept->rpdev;
>  	u32 src = ept->addr, dst = rpdev->dst;
> 
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
>  }
> -EXPORT_SYMBOL(rpmsg_send);
> 
>  /**
>   * rpmsg_sendto() - send a message across to the remote processor, specify
> dst
> @@ -820,11 +886,19 @@ EXPORT_SYMBOL(rpmsg_send);
>  int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
>  {
>  	struct rpmsg_device *rpdev = ept->rpdev;
> +
> +	return rpdev->sendto(ept, data, len, dst);
Ditto

> +}
> +EXPORT_SYMBOL(rpmsg_sendto);
> +
> +static int virtio_rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int
> len,
> +			       u32 dst)
> +{
> +	struct rpmsg_device *rpdev = ept->rpdev;
>  	u32 src = ept->addr;
> 
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
>  }
> -EXPORT_SYMBOL(rpmsg_sendto);
> 
>  /**
>   * rpmsg_send_offchannel() - send a message using explicit src/dst
> addresses
> @@ -851,10 +925,18 @@ int rpmsg_send_offchannel(struct rpmsg_endpoint
> *ept, u32 src, u32 dst,
>  {
>  	struct rpmsg_device *rpdev = ept->rpdev;
> 
> -	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
> +	return rpdev->send_offchannel(ept, src, dst, data, len);
>  }
>  EXPORT_SYMBOL(rpmsg_send_offchannel);
> 
> +static int virtio_rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32
> src,
> +					u32 dst, void *data, int len)
> +{
> +	struct rpmsg_device *rpdev = ept->rpdev;
> +
> +	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
> +}
> +
>  /**
>   * rpmsg_send() - send a message across to the remote processor
>   * @ept: the rpmsg endpoint
> @@ -875,11 +957,18 @@ EXPORT_SYMBOL(rpmsg_send_offchannel);
>  int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
>  {
>  	struct rpmsg_device *rpdev = ept->rpdev;
> +
> +	return rpdev->trysend(ept, data, len);
ditto
> +}
> +EXPORT_SYMBOL(rpmsg_trysend);
> +
> +static int virtio_rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int
> len)
> +{
> +	struct rpmsg_device *rpdev = ept->rpdev;
>  	u32 src = ept->addr, dst = rpdev->dst;
> 
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
>  }
> -EXPORT_SYMBOL(rpmsg_trysend);
> 
>  /**
>   * rpmsg_sendto() - send a message across to the remote processor, specify
> dst
> @@ -901,11 +990,19 @@ EXPORT_SYMBOL(rpmsg_trysend);
>  int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32
> dst)
>  {
>  	struct rpmsg_device *rpdev = ept->rpdev;
> +
> +	return rpdev->trysendto(ept, data, len, dst);
ditto
> +}
> +EXPORT_SYMBOL(rpmsg_trysendto);
> +
> +static int virtio_rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data,
> +				  int len, u32 dst)
> +{
> +	struct rpmsg_device *rpdev = ept->rpdev;
>  	u32 src = ept->addr;
> 
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
>  }
> -EXPORT_SYMBOL(rpmsg_trysendto);
> 
>  /**
>   * rpmsg_send_offchannel() - send a message using explicit src/dst
> addresses
> @@ -931,10 +1028,18 @@ int rpmsg_trysend_offchannel(struct
> rpmsg_endpoint *ept, u32 src, u32 dst,
>  {
>  	struct rpmsg_device *rpdev = ept->rpdev;
> 
> -	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
> +	return rpdev->trysend_offchannel(ept, src, dst, data, len);
ditto
>  }
>  EXPORT_SYMBOL(rpmsg_trysend_offchannel);
> 
> +static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept,
> u32 src,
> +					   u32 dst, void *data, int len)
> +{
> +	struct rpmsg_device *rpdev = ept->rpdev;
> +
> +	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
> +}
> +
>  static int rpmsg_recv_single(struct virtproc_info *vrp, struct device *dev,
>  			     struct rpmsg_hdr *msg, unsigned int len)
>  {
> diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
> index 3e3d5b1c154a..0b290ae18e70 100644
> --- a/include/linux/rpmsg.h
> +++ b/include/linux/rpmsg.h
> @@ -96,6 +96,10 @@ enum rpmsg_ns_flags {
>  #define RPMSG_ADDR_ANY		0xFFFFFFFF
> 
>  struct virtproc_info;
> +struct rpmsg_device;
> +struct rpmsg_endpoint;
> +
> +typedef void (*rpmsg_rx_cb_t)(struct rpmsg_device *, void *, int, void *,
> u32);
> 
>  /**
>   * rpmsg_device - device that belong to the rpmsg bus
> @@ -115,9 +119,24 @@ struct rpmsg_device {
>  	u32 dst;
>  	struct rpmsg_endpoint *ept;
>  	bool announce;
> -};
> 
> -typedef void (*rpmsg_rx_cb_t)(struct rpmsg_device *, void *, int, void *,
> u32);
> +	struct rpmsg_endpoint *(*create_ept)(struct rpmsg_device *rpdev,
> +					    rpmsg_rx_cb_t cb, void *priv, u32
> addr);
> +	void (*destroy_ept)(struct rpmsg_endpoint *ept);
> +
> +	int (*send)(struct rpmsg_endpoint *ept, void *data, int len);
> +	int (*sendto)(struct rpmsg_endpoint *ept, void *data, int len, u32
> dst);
> +	int (*send_offchannel)(struct rpmsg_endpoint *ept, u32 src, u32 dst,
> +				  void *data, int len);
> +
> +	int (*trysend)(struct rpmsg_endpoint *ept, void *data, int len);
> +	int (*trysendto)(struct rpmsg_endpoint *ept, void *data, int len, u32
> dst);
> +	int (*trysend_offchannel)(struct rpmsg_endpoint *ept, u32 src, u32
> dst,
> +			     void *data, int len);
> +
> +	int (*announce_create)(struct rpmsg_device *ept);
> +	int (*announce_destroy)(struct rpmsg_device *ept);
> +};
It will be nice to document if ops are mandatory or optional.

Regards,
Loic
> 
>  /**
>   * struct rpmsg_endpoint - binds a local rpmsg address to its user
> --
> 2.5.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-remoteproc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 54+ messages in thread

* [PATCH 06/14] rpmsg: Indirect all virtio related function calls
@ 2016-08-18 12:14     ` Loic PALLARDY
  0 siblings, 0 replies; 54+ messages in thread
From: Loic PALLARDY @ 2016-08-18 12:14 UTC (permalink / raw)
  To: linux-arm-kernel



> -----Original Message-----
> From: linux-remoteproc-owner at vger.kernel.org [mailto:linux-remoteproc-
> owner at vger.kernel.org] On Behalf Of Bjorn Andersson
> Sent: Tuesday, August 16, 2016 2:17 AM
> To: Ohad Ben-Cohen <ohad@wizery.com>; Bjorn Andersson
> <bjorn.andersson@linaro.org>
> Cc: linux-remoteproc at vger.kernel.org; linux-arm-msm at vger.kernel.org;
> linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org
> Subject: [PATCH 06/14] rpmsg: Indirect all virtio related function calls
> 
> Create indirections for functions in prepration for splitting the rpmsg
> core functionality from the virtio backend.
> 
> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> ---
>  drivers/rpmsg/virtio_rpmsg_bus.c | 131
> +++++++++++++++++++++++++++++++++++----
>  include/linux/rpmsg.h            |  23 ++++++-
>  2 files changed, 139 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c
> b/drivers/rpmsg/virtio_rpmsg_bus.c
> index a9f8cc8d968b..1dc7a1149c51 100644
> --- a/drivers/rpmsg/virtio_rpmsg_bus.c
> +++ b/drivers/rpmsg/virtio_rpmsg_bus.c
> @@ -119,6 +119,17 @@ struct rpmsg_channel_info {
>  /* Address 53 is reserved for advertising remote services */
>  #define RPMSG_NS_ADDR			(53)
> 
> +static int virtio_rpmsg_send(struct rpmsg_endpoint *ept, void *data, int
> len);
> +static int virtio_rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int
> len,
> +			       u32 dst);
> +static int virtio_rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32
> src,
> +					u32 dst, void *data, int len);
> +static int virtio_rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int
> len);
> +static int virtio_rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data,
> +				  int len, u32 dst);
> +static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept,
> u32 src,
> +					   u32 dst, void *data, int len);
> +
>  /* sysfs show configuration fields */
>  #define rpmsg_show_attr(field, path, format_string)			\
>  static ssize_t								\
> @@ -297,10 +308,17 @@ free_ept:
>  struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev,
>  					rpmsg_rx_cb_t cb, void *priv, u32
> addr)
>  {
> -	return __rpmsg_create_ept(rpdev->vrp, rpdev, cb, priv, addr);
> +	return rpdev->create_ept(rpdev, cb, priv, addr);
Hi Bjorn,

It will be good to test if pointer is valid before calling function.

>  }
>  EXPORT_SYMBOL(rpmsg_create_ept);
> 
> +static struct rpmsg_endpoint *virtio_rpmsg_create_ept(struct
> rpmsg_device *rpdev,
> +						      rpmsg_rx_cb_t cb,
> +						      void *priv, u32 addr)
> +{
> +	return __rpmsg_create_ept(rpdev->vrp, rpdev, cb, priv, addr);
> +}
> +
>  /**
>   * __rpmsg_destroy_ept() - destroy an existing rpmsg endpoint
>   * @vrp: virtproc which owns this ept
> @@ -336,10 +354,15 @@ __rpmsg_destroy_ept(struct virtproc_info *vrp,
> struct rpmsg_endpoint *ept)
>   */
>  void rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
>  {
> -	__rpmsg_destroy_ept(ept->rpdev->vrp, ept);
> +	ept->rpdev->destroy_ept(ept);
Ditto

>  }
>  EXPORT_SYMBOL(rpmsg_destroy_ept);
> 
> +static void virtio_rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
> +{
> +	__rpmsg_destroy_ept(ept->rpdev->vrp, ept);
> +}
> +
>  /*
>   * when an rpmsg driver is probed with a channel, we seamlessly create
>   * it an endpoint, binding its rx callback to a unique local rpmsg
> @@ -352,7 +375,6 @@ static int rpmsg_dev_probe(struct device *dev)
>  {
>  	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
>  	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
> -	struct virtproc_info *vrp = rpdev->vrp;
>  	struct rpmsg_endpoint *ept;
>  	int err;
> 
> @@ -373,6 +395,18 @@ static int rpmsg_dev_probe(struct device *dev)
>  		goto out;
>  	}
> 
> +	if (rpdev->announce_create)
> +		err = rpdev->announce_create(rpdev);
> +out:
> +	return err;
> +}
> +
> +static int virtio_rpmsg_announce_create(struct rpmsg_device *rpdev)
> +{
> +	struct virtproc_info *vrp = rpdev->vrp;
> +	struct device *dev = &rpdev->dev;
> +	int err = 0;
> +
>  	/* need to tell remote processor's name service about this channel ?
> */
>  	if (rpdev->announce &&
>  	    virtio_has_feature(vrp->vdev, VIRTIO_RPMSG_F_NS)) {
> @@ -387,15 +421,13 @@ static int rpmsg_dev_probe(struct device *dev)
>  			dev_err(dev, "failed to announce service %d\n", err);
>  	}
> 
> -out:
>  	return err;
>  }
> 
> -static int rpmsg_dev_remove(struct device *dev)
> +static int virtio_rpmsg_announce_destroy(struct rpmsg_device *rpdev)
>  {
> -	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> -	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
>  	struct virtproc_info *vrp = rpdev->vrp;
> +	struct device *dev = &rpdev->dev;
>  	int err = 0;
> 
>  	/* tell remote processor's name service we're removing this channel
> */
> @@ -412,6 +444,18 @@ static int rpmsg_dev_remove(struct device *dev)
>  			dev_err(dev, "failed to announce service %d\n", err);
>  	}
> 
> +	return err;
> +}
> +
> +static int rpmsg_dev_remove(struct device *dev)
> +{
> +	struct rpmsg_device *rpdev = to_rpmsg_device(dev);
> +	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
> +	int err = 0;
> +
> +	if (rpdev->announce_destroy)
> +		err = rpdev->announce_destroy(rpdev);
> +
>  	rpdrv->remove(rpdev);
> 
>  	rpmsg_destroy_ept(rpdev->ept);
> @@ -485,6 +529,19 @@ static int rpmsg_device_match(struct device *dev,
> void *data)
>  	return 1;
>  }
> 
> +static const struct rpmsg_device virtio_rpmsg_ops = {
> +	.create_ept = virtio_rpmsg_create_ept,
> +	.destroy_ept = virtio_rpmsg_destroy_ept,
> +	.send = virtio_rpmsg_send,
> +	.sendto = virtio_rpmsg_sendto,
> +	.send_offchannel = virtio_rpmsg_send_offchannel,
> +	.trysend = virtio_rpmsg_trysend,
> +	.trysendto = virtio_rpmsg_trysendto,
> +	.trysend_offchannel = virtio_rpmsg_trysend_offchannel,
> +	.announce_create = virtio_rpmsg_announce_create,
> +	.announce_destroy = virtio_rpmsg_announce_destroy,
> +};
Why not creating a dedicated ops struct like other framework?
Here ops are mixed with other parameters.

> +
>  /*
>   * create an rpmsg channel using its name and address info.
>   * this function will be used to create both static and dynamic
> @@ -511,6 +568,9 @@ static struct rpmsg_device
> *rpmsg_create_channel(struct virtproc_info *vrp,
>  	if (!rpdev)
>  		return NULL;
> 
> +	/* Assign callbacks for rpmsg_channel */
> +	*rpdev = virtio_rpmsg_ops;
It is not a simple affectation behind this operation, more a memcopy of the complete struct.
Not easy to read from my pov.
> +
>  	rpdev->vrp = vrp;
>  	rpdev->src = chinfo->src;
>  	rpdev->dst = chinfo->dst;
> @@ -793,11 +853,17 @@ out:
>  int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
>  {
>  	struct rpmsg_device *rpdev = ept->rpdev;
> +
> +	return rpdev->send(ept, data, len);
Test pointer before using it

> +}
> +
> +static int virtio_rpmsg_send(struct rpmsg_endpoint *ept, void *data, int
> len)
> +{
> +	struct rpmsg_device *rpdev = ept->rpdev;
>  	u32 src = ept->addr, dst = rpdev->dst;
> 
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
>  }
> -EXPORT_SYMBOL(rpmsg_send);
> 
>  /**
>   * rpmsg_sendto() - send a message across to the remote processor, specify
> dst
> @@ -820,11 +886,19 @@ EXPORT_SYMBOL(rpmsg_send);
>  int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
>  {
>  	struct rpmsg_device *rpdev = ept->rpdev;
> +
> +	return rpdev->sendto(ept, data, len, dst);
Ditto

> +}
> +EXPORT_SYMBOL(rpmsg_sendto);
> +
> +static int virtio_rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int
> len,
> +			       u32 dst)
> +{
> +	struct rpmsg_device *rpdev = ept->rpdev;
>  	u32 src = ept->addr;
> 
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
>  }
> -EXPORT_SYMBOL(rpmsg_sendto);
> 
>  /**
>   * rpmsg_send_offchannel() - send a message using explicit src/dst
> addresses
> @@ -851,10 +925,18 @@ int rpmsg_send_offchannel(struct rpmsg_endpoint
> *ept, u32 src, u32 dst,
>  {
>  	struct rpmsg_device *rpdev = ept->rpdev;
> 
> -	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
> +	return rpdev->send_offchannel(ept, src, dst, data, len);
>  }
>  EXPORT_SYMBOL(rpmsg_send_offchannel);
> 
> +static int virtio_rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32
> src,
> +					u32 dst, void *data, int len)
> +{
> +	struct rpmsg_device *rpdev = ept->rpdev;
> +
> +	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
> +}
> +
>  /**
>   * rpmsg_send() - send a message across to the remote processor
>   * @ept: the rpmsg endpoint
> @@ -875,11 +957,18 @@ EXPORT_SYMBOL(rpmsg_send_offchannel);
>  int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
>  {
>  	struct rpmsg_device *rpdev = ept->rpdev;
> +
> +	return rpdev->trysend(ept, data, len);
ditto
> +}
> +EXPORT_SYMBOL(rpmsg_trysend);
> +
> +static int virtio_rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int
> len)
> +{
> +	struct rpmsg_device *rpdev = ept->rpdev;
>  	u32 src = ept->addr, dst = rpdev->dst;
> 
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
>  }
> -EXPORT_SYMBOL(rpmsg_trysend);
> 
>  /**
>   * rpmsg_sendto() - send a message across to the remote processor, specify
> dst
> @@ -901,11 +990,19 @@ EXPORT_SYMBOL(rpmsg_trysend);
>  int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32
> dst)
>  {
>  	struct rpmsg_device *rpdev = ept->rpdev;
> +
> +	return rpdev->trysendto(ept, data, len, dst);
ditto
> +}
> +EXPORT_SYMBOL(rpmsg_trysendto);
> +
> +static int virtio_rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data,
> +				  int len, u32 dst)
> +{
> +	struct rpmsg_device *rpdev = ept->rpdev;
>  	u32 src = ept->addr;
> 
>  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
>  }
> -EXPORT_SYMBOL(rpmsg_trysendto);
> 
>  /**
>   * rpmsg_send_offchannel() - send a message using explicit src/dst
> addresses
> @@ -931,10 +1028,18 @@ int rpmsg_trysend_offchannel(struct
> rpmsg_endpoint *ept, u32 src, u32 dst,
>  {
>  	struct rpmsg_device *rpdev = ept->rpdev;
> 
> -	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
> +	return rpdev->trysend_offchannel(ept, src, dst, data, len);
ditto
>  }
>  EXPORT_SYMBOL(rpmsg_trysend_offchannel);
> 
> +static int virtio_rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept,
> u32 src,
> +					   u32 dst, void *data, int len)
> +{
> +	struct rpmsg_device *rpdev = ept->rpdev;
> +
> +	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, false);
> +}
> +
>  static int rpmsg_recv_single(struct virtproc_info *vrp, struct device *dev,
>  			     struct rpmsg_hdr *msg, unsigned int len)
>  {
> diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
> index 3e3d5b1c154a..0b290ae18e70 100644
> --- a/include/linux/rpmsg.h
> +++ b/include/linux/rpmsg.h
> @@ -96,6 +96,10 @@ enum rpmsg_ns_flags {
>  #define RPMSG_ADDR_ANY		0xFFFFFFFF
> 
>  struct virtproc_info;
> +struct rpmsg_device;
> +struct rpmsg_endpoint;
> +
> +typedef void (*rpmsg_rx_cb_t)(struct rpmsg_device *, void *, int, void *,
> u32);
> 
>  /**
>   * rpmsg_device - device that belong to the rpmsg bus
> @@ -115,9 +119,24 @@ struct rpmsg_device {
>  	u32 dst;
>  	struct rpmsg_endpoint *ept;
>  	bool announce;
> -};
> 
> -typedef void (*rpmsg_rx_cb_t)(struct rpmsg_device *, void *, int, void *,
> u32);
> +	struct rpmsg_endpoint *(*create_ept)(struct rpmsg_device *rpdev,
> +					    rpmsg_rx_cb_t cb, void *priv, u32
> addr);
> +	void (*destroy_ept)(struct rpmsg_endpoint *ept);
> +
> +	int (*send)(struct rpmsg_endpoint *ept, void *data, int len);
> +	int (*sendto)(struct rpmsg_endpoint *ept, void *data, int len, u32
> dst);
> +	int (*send_offchannel)(struct rpmsg_endpoint *ept, u32 src, u32 dst,
> +				  void *data, int len);
> +
> +	int (*trysend)(struct rpmsg_endpoint *ept, void *data, int len);
> +	int (*trysendto)(struct rpmsg_endpoint *ept, void *data, int len, u32
> dst);
> +	int (*trysend_offchannel)(struct rpmsg_endpoint *ept, u32 src, u32
> dst,
> +			     void *data, int len);
> +
> +	int (*announce_create)(struct rpmsg_device *ept);
> +	int (*announce_destroy)(struct rpmsg_device *ept);
> +};
It will be nice to document if ops are mandatory or optional.

Regards,
Loic
> 
>  /**
>   * struct rpmsg_endpoint - binds a local rpmsg address to its user
> --
> 2.5.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-remoteproc" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 03/14] rpmsg: rpmsg_send() operations takes rpmsg_endpoint
  2016-08-18  7:36     ` Loic PALLARDY
  (?)
  (?)
@ 2016-08-18 18:04       ` Bjorn Andersson
  -1 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-18 18:04 UTC (permalink / raw)
  To: Loic PALLARDY
  Cc: Ohad Ben-Cohen, linux-remoteproc, linux-arm-msm,
	linux-arm-kernel, linux-kernel

On Thu 18 Aug 00:36 PDT 2016, Loic PALLARDY wrote:

> 
> 
> > -----Original Message-----
> > From: linux-remoteproc-owner@vger.kernel.org [mailto:linux-remoteproc-
[..]
> > The rpmsg_send() operations has been taking a rpmsg_device, but this
> > forces users of secondary rpmsg_endpoints to use the rpmsg_sendto()
> > interface - by extracting source and destination from the given data
> > structures. If we instead pass the rpmsg_endpoint to these functions a
> > service can use rpmsg_sendto() to respond to messages, even on secondary
> > endpoints.
> > 
> > In addition this would allow us to support operations on multiple
> > channels in future backends that does not support off-channel
> > operations.
> > 
> Hi Bjorn,
> 
> This patch is modifying rpmsg API by using rpmsg_endpoint as argument
> instead of rpmsg_device.
> But associated port of rpmsg_client_sample driver is missing in your patch series.
> 

Right, I will update the sample code as well.

> Please find inline few comments.
> 
> > Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> > ---
> >  drivers/rpmsg/virtio_rpmsg_bus.c |  4 +--
> >  include/linux/rpmsg.h            | 70 +++++++++++++++++++++++-----------------
> >  2 files changed, 42 insertions(+), 32 deletions(-)
> > 
> > diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c
> > b/drivers/rpmsg/virtio_rpmsg_bus.c
> > index c4bd89ea7681..1b63f4b7c2bd 100644
> > --- a/drivers/rpmsg/virtio_rpmsg_bus.c
> > +++ b/drivers/rpmsg/virtio_rpmsg_bus.c
> > @@ -382,7 +382,7 @@ static int rpmsg_dev_probe(struct device *dev)
> >  		nsm.addr = rpdev->src;
> 
> Since endpoint is now used to indicate source, I'm wondering if it is possible
> to suppress src field from struct rpmsg_channel and rely only on endpoint addr?
> Else maybe confusing (which src addr used at the end: rpdev or ept?)
> 

The rpdev src and dst fields are used to pass information from
rpmsg_create_channel() to the probe() where we create the associated
endpoint. So I believe the rpdev has to carry this information, in some
way.

In this particular case I believe it would be better to use
rpdev->ept->addr, to clarify that we're announcing the primary endpoints
existence.

> >  		nsm.flags = RPMSG_NS_CREATE;
> > 
> > -		err = rpmsg_sendto(rpdev, &nsm, sizeof(nsm),
> > RPMSG_NS_ADDR);
> > +		err = rpmsg_sendto(rpdev->ept, &nsm, sizeof(nsm),
> > RPMSG_NS_ADDR);
> >  		if (err)
> >  			dev_err(dev, "failed to announce service %d\n", err);
> >  	}
> > @@ -407,7 +407,7 @@ static int rpmsg_dev_remove(struct device *dev)
> >  		nsm.addr = rpdev->src;
> >  		nsm.flags = RPMSG_NS_DESTROY;
> > 
> > -		err = rpmsg_sendto(rpdev, &nsm, sizeof(nsm),
> > RPMSG_NS_ADDR);
> > +		err = rpmsg_sendto(rpdev->ept, &nsm, sizeof(nsm),
> > RPMSG_NS_ADDR);
> >  		if (err)
> >  			dev_err(dev, "failed to announce service %d\n", err);
> >  	}
> > diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
[..]
> > -static inline int rpmsg_send(struct rpmsg_channel *rpdev, void *data, int
> > len)
> > +static inline int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int
> > len)
> >  {
> > -	u32 src = rpdev->src, dst = rpdev->dst;
> > +	struct rpmsg_channel *rpdev = ept->rpdev;
> > +	u32 src = ept->addr, dst = rpdev->dst;
> As this function is part of rpmsg API, it will be good to verify pointers before use.

I don't think we should be too friendly to miss-usage of the API, as
this would likely indicate a bug in the client.

That said, we can make it verbose and remove the panic by adding:

if (WARN_ON(!ept))
	return -EINVAL;

Does that sound okay?

[..]
> > +
> >  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
> >  }
> > 
> >  /**
> >   * rpmsg_send() - send a message across to the remote processor
> Function name and description not aligned with code.
> Should be rpmsg_trysend
> May be in another patch...
> 

Yeah, I noticed this too, but not until it would be annoying to rebase
my patches ontop the change; so I was planning to fix that ontop, rather
than before this refactoring.

> > - * @rpdev: the rpmsg channel
> > + * @ept: the rpmsg endpoint
> >   * @data: payload of message
> >   * @len: length of payload
> >   *
> > - * This function sends @data of length @len on the @rpdev channel.
> > - * The message will be sent to the remote processor which the @rpdev
> > - * channel belongs to, using @rpdev's source and destination addresses.
> > + * This function sends @data of length @len on the @ept endpoint.
> > + * The message will be sent to the remote processor which the @ept
> > + * endpoint belongs to, using @ept's addres as source and its associated
> > + * rpdev's address as destination.
> >   * In case there are no TX buffers available, the function will immediately
> >   * return -ENOMEM without waiting until one becomes available.
> >   *

Thanks for your feedback.

Regards,
Bjorn

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 03/14] rpmsg: rpmsg_send() operations takes rpmsg_endpoint
@ 2016-08-18 18:04       ` Bjorn Andersson
  0 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-18 18:04 UTC (permalink / raw)
  To: Loic PALLARDY
  Cc: Ohad Ben-Cohen, linux-arm-msm, linux-remoteproc, linux-kernel,
	linux-arm-kernel

On Thu 18 Aug 00:36 PDT 2016, Loic PALLARDY wrote:

> 
> 
> > -----Original Message-----
> > From: linux-remoteproc-owner@vger.kernel.org [mailto:linux-remoteproc-
[..]
> > The rpmsg_send() operations has been taking a rpmsg_device, but this
> > forces users of secondary rpmsg_endpoints to use the rpmsg_sendto()
> > interface - by extracting source and destination from the given data
> > structures. If we instead pass the rpmsg_endpoint to these functions a
> > service can use rpmsg_sendto() to respond to messages, even on secondary
> > endpoints.
> > 
> > In addition this would allow us to support operations on multiple
> > channels in future backends that does not support off-channel
> > operations.
> > 
> Hi Bjorn,
> 
> This patch is modifying rpmsg API by using rpmsg_endpoint as argument
> instead of rpmsg_device.
> But associated port of rpmsg_client_sample driver is missing in your patch series.
> 

Right, I will update the sample code as well.

> Please find inline few comments.
> 
> > Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> > ---
> >  drivers/rpmsg/virtio_rpmsg_bus.c |  4 +--
> >  include/linux/rpmsg.h            | 70 +++++++++++++++++++++++-----------------
> >  2 files changed, 42 insertions(+), 32 deletions(-)
> > 
> > diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c
> > b/drivers/rpmsg/virtio_rpmsg_bus.c
> > index c4bd89ea7681..1b63f4b7c2bd 100644
> > --- a/drivers/rpmsg/virtio_rpmsg_bus.c
> > +++ b/drivers/rpmsg/virtio_rpmsg_bus.c
> > @@ -382,7 +382,7 @@ static int rpmsg_dev_probe(struct device *dev)
> >  		nsm.addr = rpdev->src;
> 
> Since endpoint is now used to indicate source, I'm wondering if it is possible
> to suppress src field from struct rpmsg_channel and rely only on endpoint addr?
> Else maybe confusing (which src addr used at the end: rpdev or ept?)
> 

The rpdev src and dst fields are used to pass information from
rpmsg_create_channel() to the probe() where we create the associated
endpoint. So I believe the rpdev has to carry this information, in some
way.

In this particular case I believe it would be better to use
rpdev->ept->addr, to clarify that we're announcing the primary endpoints
existence.

> >  		nsm.flags = RPMSG_NS_CREATE;
> > 
> > -		err = rpmsg_sendto(rpdev, &nsm, sizeof(nsm),
> > RPMSG_NS_ADDR);
> > +		err = rpmsg_sendto(rpdev->ept, &nsm, sizeof(nsm),
> > RPMSG_NS_ADDR);
> >  		if (err)
> >  			dev_err(dev, "failed to announce service %d\n", err);
> >  	}
> > @@ -407,7 +407,7 @@ static int rpmsg_dev_remove(struct device *dev)
> >  		nsm.addr = rpdev->src;
> >  		nsm.flags = RPMSG_NS_DESTROY;
> > 
> > -		err = rpmsg_sendto(rpdev, &nsm, sizeof(nsm),
> > RPMSG_NS_ADDR);
> > +		err = rpmsg_sendto(rpdev->ept, &nsm, sizeof(nsm),
> > RPMSG_NS_ADDR);
> >  		if (err)
> >  			dev_err(dev, "failed to announce service %d\n", err);
> >  	}
> > diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
[..]
> > -static inline int rpmsg_send(struct rpmsg_channel *rpdev, void *data, int
> > len)
> > +static inline int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int
> > len)
> >  {
> > -	u32 src = rpdev->src, dst = rpdev->dst;
> > +	struct rpmsg_channel *rpdev = ept->rpdev;
> > +	u32 src = ept->addr, dst = rpdev->dst;
> As this function is part of rpmsg API, it will be good to verify pointers before use.

I don't think we should be too friendly to miss-usage of the API, as
this would likely indicate a bug in the client.

That said, we can make it verbose and remove the panic by adding:

if (WARN_ON(!ept))
	return -EINVAL;

Does that sound okay?

[..]
> > +
> >  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
> >  }
> > 
> >  /**
> >   * rpmsg_send() - send a message across to the remote processor
> Function name and description not aligned with code.
> Should be rpmsg_trysend
> May be in another patch...
> 

Yeah, I noticed this too, but not until it would be annoying to rebase
my patches ontop the change; so I was planning to fix that ontop, rather
than before this refactoring.

> > - * @rpdev: the rpmsg channel
> > + * @ept: the rpmsg endpoint
> >   * @data: payload of message
> >   * @len: length of payload
> >   *
> > - * This function sends @data of length @len on the @rpdev channel.
> > - * The message will be sent to the remote processor which the @rpdev
> > - * channel belongs to, using @rpdev's source and destination addresses.
> > + * This function sends @data of length @len on the @ept endpoint.
> > + * The message will be sent to the remote processor which the @ept
> > + * endpoint belongs to, using @ept's addres as source and its associated
> > + * rpdev's address as destination.
> >   * In case there are no TX buffers available, the function will immediately
> >   * return -ENOMEM without waiting until one becomes available.
> >   *

Thanks for your feedback.

Regards,
Bjorn

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 03/14] rpmsg: rpmsg_send() operations takes rpmsg_endpoint
@ 2016-08-18 18:04       ` Bjorn Andersson
  0 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-18 18:04 UTC (permalink / raw)
  To: Loic PALLARDY
  Cc: Ohad Ben-Cohen, linux-remoteproc, linux-arm-msm,
	linux-arm-kernel, linux-kernel

On Thu 18 Aug 00:36 PDT 2016, Loic PALLARDY wrote:

> 
> 
> > -----Original Message-----
> > From: linux-remoteproc-owner@vger.kernel.org [mailto:linux-remoteproc-
[..]
> > The rpmsg_send() operations has been taking a rpmsg_device, but this
> > forces users of secondary rpmsg_endpoints to use the rpmsg_sendto()
> > interface - by extracting source and destination from the given data
> > structures. If we instead pass the rpmsg_endpoint to these functions a
> > service can use rpmsg_sendto() to respond to messages, even on secondary
> > endpoints.
> > 
> > In addition this would allow us to support operations on multiple
> > channels in future backends that does not support off-channel
> > operations.
> > 
> Hi Bjorn,
> 
> This patch is modifying rpmsg API by using rpmsg_endpoint as argument
> instead of rpmsg_device.
> But associated port of rpmsg_client_sample driver is missing in your patch series.
> 

Right, I will update the sample code as well.

> Please find inline few comments.
> 
> > Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> > ---
> >  drivers/rpmsg/virtio_rpmsg_bus.c |  4 +--
> >  include/linux/rpmsg.h            | 70 +++++++++++++++++++++++-----------------
> >  2 files changed, 42 insertions(+), 32 deletions(-)
> > 
> > diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c
> > b/drivers/rpmsg/virtio_rpmsg_bus.c
> > index c4bd89ea7681..1b63f4b7c2bd 100644
> > --- a/drivers/rpmsg/virtio_rpmsg_bus.c
> > +++ b/drivers/rpmsg/virtio_rpmsg_bus.c
> > @@ -382,7 +382,7 @@ static int rpmsg_dev_probe(struct device *dev)
> >  		nsm.addr = rpdev->src;
> 
> Since endpoint is now used to indicate source, I'm wondering if it is possible
> to suppress src field from struct rpmsg_channel and rely only on endpoint addr?
> Else maybe confusing (which src addr used at the end: rpdev or ept?)
> 

The rpdev src and dst fields are used to pass information from
rpmsg_create_channel() to the probe() where we create the associated
endpoint. So I believe the rpdev has to carry this information, in some
way.

In this particular case I believe it would be better to use
rpdev->ept->addr, to clarify that we're announcing the primary endpoints
existence.

> >  		nsm.flags = RPMSG_NS_CREATE;
> > 
> > -		err = rpmsg_sendto(rpdev, &nsm, sizeof(nsm),
> > RPMSG_NS_ADDR);
> > +		err = rpmsg_sendto(rpdev->ept, &nsm, sizeof(nsm),
> > RPMSG_NS_ADDR);
> >  		if (err)
> >  			dev_err(dev, "failed to announce service %d\n", err);
> >  	}
> > @@ -407,7 +407,7 @@ static int rpmsg_dev_remove(struct device *dev)
> >  		nsm.addr = rpdev->src;
> >  		nsm.flags = RPMSG_NS_DESTROY;
> > 
> > -		err = rpmsg_sendto(rpdev, &nsm, sizeof(nsm),
> > RPMSG_NS_ADDR);
> > +		err = rpmsg_sendto(rpdev->ept, &nsm, sizeof(nsm),
> > RPMSG_NS_ADDR);
> >  		if (err)
> >  			dev_err(dev, "failed to announce service %d\n", err);
> >  	}
> > diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
[..]
> > -static inline int rpmsg_send(struct rpmsg_channel *rpdev, void *data, int
> > len)
> > +static inline int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int
> > len)
> >  {
> > -	u32 src = rpdev->src, dst = rpdev->dst;
> > +	struct rpmsg_channel *rpdev = ept->rpdev;
> > +	u32 src = ept->addr, dst = rpdev->dst;
> As this function is part of rpmsg API, it will be good to verify pointers before use.

I don't think we should be too friendly to miss-usage of the API, as
this would likely indicate a bug in the client.

That said, we can make it verbose and remove the panic by adding:

if (WARN_ON(!ept))
	return -EINVAL;

Does that sound okay?

[..]
> > +
> >  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
> >  }
> > 
> >  /**
> >   * rpmsg_send() - send a message across to the remote processor
> Function name and description not aligned with code.
> Should be rpmsg_trysend
> May be in another patch...
> 

Yeah, I noticed this too, but not until it would be annoying to rebase
my patches ontop the change; so I was planning to fix that ontop, rather
than before this refactoring.

> > - * @rpdev: the rpmsg channel
> > + * @ept: the rpmsg endpoint
> >   * @data: payload of message
> >   * @len: length of payload
> >   *
> > - * This function sends @data of length @len on the @rpdev channel.
> > - * The message will be sent to the remote processor which the @rpdev
> > - * channel belongs to, using @rpdev's source and destination addresses.
> > + * This function sends @data of length @len on the @ept endpoint.
> > + * The message will be sent to the remote processor which the @ept
> > + * endpoint belongs to, using @ept's addres as source and its associated
> > + * rpdev's address as destination.
> >   * In case there are no TX buffers available, the function will immediately
> >   * return -ENOMEM without waiting until one becomes available.
> >   *

Thanks for your feedback.

Regards,
Bjorn

^ permalink raw reply	[flat|nested] 54+ messages in thread

* [PATCH 03/14] rpmsg: rpmsg_send() operations takes rpmsg_endpoint
@ 2016-08-18 18:04       ` Bjorn Andersson
  0 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-18 18:04 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu 18 Aug 00:36 PDT 2016, Loic PALLARDY wrote:

> 
> 
> > -----Original Message-----
> > From: linux-remoteproc-owner at vger.kernel.org [mailto:linux-remoteproc-
[..]
> > The rpmsg_send() operations has been taking a rpmsg_device, but this
> > forces users of secondary rpmsg_endpoints to use the rpmsg_sendto()
> > interface - by extracting source and destination from the given data
> > structures. If we instead pass the rpmsg_endpoint to these functions a
> > service can use rpmsg_sendto() to respond to messages, even on secondary
> > endpoints.
> > 
> > In addition this would allow us to support operations on multiple
> > channels in future backends that does not support off-channel
> > operations.
> > 
> Hi Bjorn,
> 
> This patch is modifying rpmsg API by using rpmsg_endpoint as argument
> instead of rpmsg_device.
> But associated port of rpmsg_client_sample driver is missing in your patch series.
> 

Right, I will update the sample code as well.

> Please find inline few comments.
> 
> > Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> > ---
> >  drivers/rpmsg/virtio_rpmsg_bus.c |  4 +--
> >  include/linux/rpmsg.h            | 70 +++++++++++++++++++++++-----------------
> >  2 files changed, 42 insertions(+), 32 deletions(-)
> > 
> > diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c
> > b/drivers/rpmsg/virtio_rpmsg_bus.c
> > index c4bd89ea7681..1b63f4b7c2bd 100644
> > --- a/drivers/rpmsg/virtio_rpmsg_bus.c
> > +++ b/drivers/rpmsg/virtio_rpmsg_bus.c
> > @@ -382,7 +382,7 @@ static int rpmsg_dev_probe(struct device *dev)
> >  		nsm.addr = rpdev->src;
> 
> Since endpoint is now used to indicate source, I'm wondering if it is possible
> to suppress src field from struct rpmsg_channel and rely only on endpoint addr?
> Else maybe confusing (which src addr used at the end: rpdev or ept?)
> 

The rpdev src and dst fields are used to pass information from
rpmsg_create_channel() to the probe() where we create the associated
endpoint. So I believe the rpdev has to carry this information, in some
way.

In this particular case I believe it would be better to use
rpdev->ept->addr, to clarify that we're announcing the primary endpoints
existence.

> >  		nsm.flags = RPMSG_NS_CREATE;
> > 
> > -		err = rpmsg_sendto(rpdev, &nsm, sizeof(nsm),
> > RPMSG_NS_ADDR);
> > +		err = rpmsg_sendto(rpdev->ept, &nsm, sizeof(nsm),
> > RPMSG_NS_ADDR);
> >  		if (err)
> >  			dev_err(dev, "failed to announce service %d\n", err);
> >  	}
> > @@ -407,7 +407,7 @@ static int rpmsg_dev_remove(struct device *dev)
> >  		nsm.addr = rpdev->src;
> >  		nsm.flags = RPMSG_NS_DESTROY;
> > 
> > -		err = rpmsg_sendto(rpdev, &nsm, sizeof(nsm),
> > RPMSG_NS_ADDR);
> > +		err = rpmsg_sendto(rpdev->ept, &nsm, sizeof(nsm),
> > RPMSG_NS_ADDR);
> >  		if (err)
> >  			dev_err(dev, "failed to announce service %d\n", err);
> >  	}
> > diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
[..]
> > -static inline int rpmsg_send(struct rpmsg_channel *rpdev, void *data, int
> > len)
> > +static inline int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int
> > len)
> >  {
> > -	u32 src = rpdev->src, dst = rpdev->dst;
> > +	struct rpmsg_channel *rpdev = ept->rpdev;
> > +	u32 src = ept->addr, dst = rpdev->dst;
> As this function is part of rpmsg API, it will be good to verify pointers before use.

I don't think we should be too friendly to miss-usage of the API, as
this would likely indicate a bug in the client.

That said, we can make it verbose and remove the panic by adding:

if (WARN_ON(!ept))
	return -EINVAL;

Does that sound okay?

[..]
> > +
> >  	return rpmsg_send_offchannel_raw(rpdev, src, dst, data, len, true);
> >  }
> > 
> >  /**
> >   * rpmsg_send() - send a message across to the remote processor
> Function name and description not aligned with code.
> Should be rpmsg_trysend
> May be in another patch...
> 

Yeah, I noticed this too, but not until it would be annoying to rebase
my patches ontop the change; so I was planning to fix that ontop, rather
than before this refactoring.

> > - * @rpdev: the rpmsg channel
> > + * @ept: the rpmsg endpoint
> >   * @data: payload of message
> >   * @len: length of payload
> >   *
> > - * This function sends @data of length @len on the @rpdev channel.
> > - * The message will be sent to the remote processor which the @rpdev
> > - * channel belongs to, using @rpdev's source and destination addresses.
> > + * This function sends @data of length @len on the @ept endpoint.
> > + * The message will be sent to the remote processor which the @ept
> > + * endpoint belongs to, using @ept's addres as source and its associated
> > + * rpdev's address as destination.
> >   * In case there are no TX buffers available, the function will immediately
> >   * return -ENOMEM without waiting until one becomes available.
> >   *

Thanks for your feedback.

Regards,
Bjorn

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 08/14] rpmsg: Split rpmsg core and virtio backend
  2016-08-18 11:59     ` Loic PALLARDY
  (?)
  (?)
@ 2016-08-18 18:09       ` Bjorn Andersson
  -1 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-18 18:09 UTC (permalink / raw)
  To: Loic PALLARDY
  Cc: Ohad Ben-Cohen, linux-remoteproc, linux-arm-msm,
	linux-arm-kernel, linux-kernel, Sricharan R

On Thu 18 Aug 04:59 PDT 2016, Loic PALLARDY wrote:

> 
> 
> > -----Original Message-----
> > From: linux-remoteproc-owner@vger.kernel.org [mailto:linux-remoteproc-
> > owner@vger.kernel.org] On Behalf Of Bjorn Andersson
> > Sent: Tuesday, August 16, 2016 2:17 AM
> > To: Ohad Ben-Cohen <ohad@wizery.com>; Bjorn Andersson
> > <bjorn.andersson@linaro.org>
> > Cc: linux-remoteproc@vger.kernel.org; linux-arm-msm@vger.kernel.org;
> > linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org;
> > Sricharan R <sricharan@codeaurora.org>
> > Subject: [PATCH 08/14] rpmsg: Split rpmsg core and virtio backend
> > 
> > Extract the generic rpmsg core functionality from the virtio rpmsg
> > implementation, splitting the implementation in a rpmsg core and a
> > virtio backend.
> > 
> > Based on initial work by Sricharan R <sricharan@codeaurora.org>
> > 
> > Cc: Sricharan R <sricharan@codeaurora.org>
> > Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> > ---
> >  drivers/rpmsg/Kconfig            |   4 +
> >  drivers/rpmsg/Makefile           |   3 +-
> >  drivers/rpmsg/rpmsg_core.c       | 513
> > +++++++++++++++++++++++++++++++++++++++
> >  drivers/rpmsg/rpmsg_internal.h   |  45 ++++
> >  drivers/rpmsg/virtio_rpmsg_bus.c | 477 +-----------------------------------
> Hi Bjorn,
> 
> Could you please regenerate the patch with  option -M (of git
> formatpatch) to detect file renames.  It will provide better
> visibility of differences between virtio_rpmsg_bus.c and rpmsg_core.c.

I believe this is with -M, but as I only extracted part of the file it
did not detect it as a rename. I will see if I can figure something out
for v2.

Perhaps if I split the move in more than one commit it will be easier to
follow; like take the device management in one chunk and the
rpmsg_send() functions in one would reduce the size of the two patches
quite a bit.

> 
> >  5 files changed, 569 insertions(+), 473 deletions(-)
> >  create mode 100644 drivers/rpmsg/rpmsg_core.c
> >  create mode 100644 drivers/rpmsg/rpmsg_internal.h
> > 
> > diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig
> > index 69a219387582..40614be88c97 100644
> > --- a/drivers/rpmsg/Kconfig
> > +++ b/drivers/rpmsg/Kconfig
> > @@ -3,6 +3,10 @@ menu "Rpmsg drivers"
> >  # RPMSG always gets selected by whoever wants it
> >  config RPMSG
> >  	tristate
> > +
> > +config RPMSG_VIRTIO
> > +	tristate
> > +	select RPMSG
> >  	select VIRTIO
> >  	select VIRTUALIZATION
> > 
> Remoteproc Kconfig should be changed too to select RPMSG_VIRTIO instead of RPMSG.
> 

You're right, forgot to include that. I still think this should be a
user selectable option, rather than being tied to particular remoteproc
drivers - but let's take that discussion separately.

Thanks,
Bjorn

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 08/14] rpmsg: Split rpmsg core and virtio backend
@ 2016-08-18 18:09       ` Bjorn Andersson
  0 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-18 18:09 UTC (permalink / raw)
  To: Loic PALLARDY
  Cc: Ohad Ben-Cohen, linux-arm-msm, linux-remoteproc, linux-kernel,
	Sricharan R, linux-arm-kernel

On Thu 18 Aug 04:59 PDT 2016, Loic PALLARDY wrote:

> 
> 
> > -----Original Message-----
> > From: linux-remoteproc-owner@vger.kernel.org [mailto:linux-remoteproc-
> > owner@vger.kernel.org] On Behalf Of Bjorn Andersson
> > Sent: Tuesday, August 16, 2016 2:17 AM
> > To: Ohad Ben-Cohen <ohad@wizery.com>; Bjorn Andersson
> > <bjorn.andersson@linaro.org>
> > Cc: linux-remoteproc@vger.kernel.org; linux-arm-msm@vger.kernel.org;
> > linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org;
> > Sricharan R <sricharan@codeaurora.org>
> > Subject: [PATCH 08/14] rpmsg: Split rpmsg core and virtio backend
> > 
> > Extract the generic rpmsg core functionality from the virtio rpmsg
> > implementation, splitting the implementation in a rpmsg core and a
> > virtio backend.
> > 
> > Based on initial work by Sricharan R <sricharan@codeaurora.org>
> > 
> > Cc: Sricharan R <sricharan@codeaurora.org>
> > Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> > ---
> >  drivers/rpmsg/Kconfig            |   4 +
> >  drivers/rpmsg/Makefile           |   3 +-
> >  drivers/rpmsg/rpmsg_core.c       | 513
> > +++++++++++++++++++++++++++++++++++++++
> >  drivers/rpmsg/rpmsg_internal.h   |  45 ++++
> >  drivers/rpmsg/virtio_rpmsg_bus.c | 477 +-----------------------------------
> Hi Bjorn,
> 
> Could you please regenerate the patch with  option -M (of git
> formatpatch) to detect file renames.  It will provide better
> visibility of differences between virtio_rpmsg_bus.c and rpmsg_core.c.

I believe this is with -M, but as I only extracted part of the file it
did not detect it as a rename. I will see if I can figure something out
for v2.

Perhaps if I split the move in more than one commit it will be easier to
follow; like take the device management in one chunk and the
rpmsg_send() functions in one would reduce the size of the two patches
quite a bit.

> 
> >  5 files changed, 569 insertions(+), 473 deletions(-)
> >  create mode 100644 drivers/rpmsg/rpmsg_core.c
> >  create mode 100644 drivers/rpmsg/rpmsg_internal.h
> > 
> > diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig
> > index 69a219387582..40614be88c97 100644
> > --- a/drivers/rpmsg/Kconfig
> > +++ b/drivers/rpmsg/Kconfig
> > @@ -3,6 +3,10 @@ menu "Rpmsg drivers"
> >  # RPMSG always gets selected by whoever wants it
> >  config RPMSG
> >  	tristate
> > +
> > +config RPMSG_VIRTIO
> > +	tristate
> > +	select RPMSG
> >  	select VIRTIO
> >  	select VIRTUALIZATION
> > 
> Remoteproc Kconfig should be changed too to select RPMSG_VIRTIO instead of RPMSG.
> 

You're right, forgot to include that. I still think this should be a
user selectable option, rather than being tied to particular remoteproc
drivers - but let's take that discussion separately.

Thanks,
Bjorn

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 08/14] rpmsg: Split rpmsg core and virtio backend
@ 2016-08-18 18:09       ` Bjorn Andersson
  0 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-18 18:09 UTC (permalink / raw)
  To: Loic PALLARDY
  Cc: Ohad Ben-Cohen, linux-remoteproc, linux-arm-msm,
	linux-arm-kernel, linux-kernel, Sricharan R

On Thu 18 Aug 04:59 PDT 2016, Loic PALLARDY wrote:

> 
> 
> > -----Original Message-----
> > From: linux-remoteproc-owner@vger.kernel.org [mailto:linux-remoteproc-
> > owner@vger.kernel.org] On Behalf Of Bjorn Andersson
> > Sent: Tuesday, August 16, 2016 2:17 AM
> > To: Ohad Ben-Cohen <ohad@wizery.com>; Bjorn Andersson
> > <bjorn.andersson@linaro.org>
> > Cc: linux-remoteproc@vger.kernel.org; linux-arm-msm@vger.kernel.org;
> > linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org;
> > Sricharan R <sricharan@codeaurora.org>
> > Subject: [PATCH 08/14] rpmsg: Split rpmsg core and virtio backend
> > 
> > Extract the generic rpmsg core functionality from the virtio rpmsg
> > implementation, splitting the implementation in a rpmsg core and a
> > virtio backend.
> > 
> > Based on initial work by Sricharan R <sricharan@codeaurora.org>
> > 
> > Cc: Sricharan R <sricharan@codeaurora.org>
> > Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> > ---
> >  drivers/rpmsg/Kconfig            |   4 +
> >  drivers/rpmsg/Makefile           |   3 +-
> >  drivers/rpmsg/rpmsg_core.c       | 513
> > +++++++++++++++++++++++++++++++++++++++
> >  drivers/rpmsg/rpmsg_internal.h   |  45 ++++
> >  drivers/rpmsg/virtio_rpmsg_bus.c | 477 +-----------------------------------
> Hi Bjorn,
> 
> Could you please regenerate the patch with  option -M (of git
> formatpatch) to detect file renames.  It will provide better
> visibility of differences between virtio_rpmsg_bus.c and rpmsg_core.c.

I believe this is with -M, but as I only extracted part of the file it
did not detect it as a rename. I will see if I can figure something out
for v2.

Perhaps if I split the move in more than one commit it will be easier to
follow; like take the device management in one chunk and the
rpmsg_send() functions in one would reduce the size of the two patches
quite a bit.

> 
> >  5 files changed, 569 insertions(+), 473 deletions(-)
> >  create mode 100644 drivers/rpmsg/rpmsg_core.c
> >  create mode 100644 drivers/rpmsg/rpmsg_internal.h
> > 
> > diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig
> > index 69a219387582..40614be88c97 100644
> > --- a/drivers/rpmsg/Kconfig
> > +++ b/drivers/rpmsg/Kconfig
> > @@ -3,6 +3,10 @@ menu "Rpmsg drivers"
> >  # RPMSG always gets selected by whoever wants it
> >  config RPMSG
> >  	tristate
> > +
> > +config RPMSG_VIRTIO
> > +	tristate
> > +	select RPMSG
> >  	select VIRTIO
> >  	select VIRTUALIZATION
> > 
> Remoteproc Kconfig should be changed too to select RPMSG_VIRTIO instead of RPMSG.
> 

You're right, forgot to include that. I still think this should be a
user selectable option, rather than being tied to particular remoteproc
drivers - but let's take that discussion separately.

Thanks,
Bjorn

^ permalink raw reply	[flat|nested] 54+ messages in thread

* [PATCH 08/14] rpmsg: Split rpmsg core and virtio backend
@ 2016-08-18 18:09       ` Bjorn Andersson
  0 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-18 18:09 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu 18 Aug 04:59 PDT 2016, Loic PALLARDY wrote:

> 
> 
> > -----Original Message-----
> > From: linux-remoteproc-owner at vger.kernel.org [mailto:linux-remoteproc-
> > owner at vger.kernel.org] On Behalf Of Bjorn Andersson
> > Sent: Tuesday, August 16, 2016 2:17 AM
> > To: Ohad Ben-Cohen <ohad@wizery.com>; Bjorn Andersson
> > <bjorn.andersson@linaro.org>
> > Cc: linux-remoteproc at vger.kernel.org; linux-arm-msm at vger.kernel.org;
> > linux-arm-kernel at lists.infradead.org; linux-kernel at vger.kernel.org;
> > Sricharan R <sricharan@codeaurora.org>
> > Subject: [PATCH 08/14] rpmsg: Split rpmsg core and virtio backend
> > 
> > Extract the generic rpmsg core functionality from the virtio rpmsg
> > implementation, splitting the implementation in a rpmsg core and a
> > virtio backend.
> > 
> > Based on initial work by Sricharan R <sricharan@codeaurora.org>
> > 
> > Cc: Sricharan R <sricharan@codeaurora.org>
> > Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> > ---
> >  drivers/rpmsg/Kconfig            |   4 +
> >  drivers/rpmsg/Makefile           |   3 +-
> >  drivers/rpmsg/rpmsg_core.c       | 513
> > +++++++++++++++++++++++++++++++++++++++
> >  drivers/rpmsg/rpmsg_internal.h   |  45 ++++
> >  drivers/rpmsg/virtio_rpmsg_bus.c | 477 +-----------------------------------
> Hi Bjorn,
> 
> Could you please regenerate the patch with  option -M (of git
> formatpatch) to detect file renames.  It will provide better
> visibility of differences between virtio_rpmsg_bus.c and rpmsg_core.c.

I believe this is with -M, but as I only extracted part of the file it
did not detect it as a rename. I will see if I can figure something out
for v2.

Perhaps if I split the move in more than one commit it will be easier to
follow; like take the device management in one chunk and the
rpmsg_send() functions in one would reduce the size of the two patches
quite a bit.

> 
> >  5 files changed, 569 insertions(+), 473 deletions(-)
> >  create mode 100644 drivers/rpmsg/rpmsg_core.c
> >  create mode 100644 drivers/rpmsg/rpmsg_internal.h
> > 
> > diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig
> > index 69a219387582..40614be88c97 100644
> > --- a/drivers/rpmsg/Kconfig
> > +++ b/drivers/rpmsg/Kconfig
> > @@ -3,6 +3,10 @@ menu "Rpmsg drivers"
> >  # RPMSG always gets selected by whoever wants it
> >  config RPMSG
> >  	tristate
> > +
> > +config RPMSG_VIRTIO
> > +	tristate
> > +	select RPMSG
> >  	select VIRTIO
> >  	select VIRTUALIZATION
> > 
> Remoteproc Kconfig should be changed too to select RPMSG_VIRTIO instead of RPMSG.
> 

You're right, forgot to include that. I still think this should be a
user selectable option, rather than being tied to particular remoteproc
drivers - but let's take that discussion separately.

Thanks,
Bjorn

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 06/14] rpmsg: Indirect all virtio related function calls
  2016-08-18 12:14     ` Loic PALLARDY
  (?)
  (?)
@ 2016-08-18 18:13       ` Bjorn Andersson
  -1 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-18 18:13 UTC (permalink / raw)
  To: Loic PALLARDY
  Cc: Ohad Ben-Cohen, linux-remoteproc, linux-arm-msm,
	linux-arm-kernel, linux-kernel

On Thu 18 Aug 05:14 PDT 2016, Loic PALLARDY wrote:

> > diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c
[..]
> >  struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev,
> >  					rpmsg_rx_cb_t cb, void *priv, u32
> > addr)
> >  {
> > -	return __rpmsg_create_ept(rpdev->vrp, rpdev, cb, priv, addr);
> > +	return rpdev->create_ept(rpdev, cb, priv, addr);
> Hi Bjorn,
> 
> It will be good to test if pointer is valid before calling function.
> 

Per the rpmsg_send() implementation, I can make it loud but friendlier
by:

if (WARN_ON(!rpdev))
	return -EINVAL;

[..]
> > 
> > +static const struct rpmsg_device virtio_rpmsg_ops = {
> > +	.create_ept = virtio_rpmsg_create_ept,
> > +	.destroy_ept = virtio_rpmsg_destroy_ept,
> > +	.send = virtio_rpmsg_send,
> > +	.sendto = virtio_rpmsg_sendto,
> > +	.send_offchannel = virtio_rpmsg_send_offchannel,
> > +	.trysend = virtio_rpmsg_trysend,
> > +	.trysendto = virtio_rpmsg_trysendto,
> > +	.trysend_offchannel = virtio_rpmsg_trysend_offchannel,
> > +	.announce_create = virtio_rpmsg_announce_create,
> > +	.announce_destroy = virtio_rpmsg_announce_destroy,
> > +};
> Why not creating a dedicated ops struct like other framework?
> Here ops are mixed with other parameters.
> 

That's a good suggestion...

> > +
> >  /*
> >   * create an rpmsg channel using its name and address info.
> >   * this function will be used to create both static and dynamic
> > @@ -511,6 +568,9 @@ static struct rpmsg_device
> > *rpmsg_create_channel(struct virtproc_info *vrp,
> >  	if (!rpdev)
> >  		return NULL;
> > 
> > +	/* Assign callbacks for rpmsg_channel */
> > +	*rpdev = virtio_rpmsg_ops;
> It is not a simple affectation behind this operation, more a memcopy of the complete struct.
> Not easy to read from my pov.

...and would clean this up. I'll do that.

> > +
> >  	rpdev->vrp = vrp;
> >  	rpdev->src = chinfo->src;
> >  	rpdev->dst = chinfo->dst;
> > @@ -793,11 +853,17 @@ out:
> >  int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
> >  {
> >  	struct rpmsg_device *rpdev = ept->rpdev;
> > +
> > +	return rpdev->send(ept, data, len);
> Test pointer before using it

Yeah, this would follow from the earlier patch.

> 
> > +}
> > +
[..]
> > diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
[..]
> > u32);
> > +	struct rpmsg_endpoint *(*create_ept)(struct rpmsg_device *rpdev,
> > +					    rpmsg_rx_cb_t cb, void *priv, u32
> > addr);
> > +	void (*destroy_ept)(struct rpmsg_endpoint *ept);
> > +
> > +	int (*send)(struct rpmsg_endpoint *ept, void *data, int len);
> > +	int (*sendto)(struct rpmsg_endpoint *ept, void *data, int len, u32
> > dst);
> > +	int (*send_offchannel)(struct rpmsg_endpoint *ept, u32 src, u32 dst,
> > +				  void *data, int len);
> > +
> > +	int (*trysend)(struct rpmsg_endpoint *ept, void *data, int len);
> > +	int (*trysendto)(struct rpmsg_endpoint *ept, void *data, int len, u32
> > dst);
> > +	int (*trysend_offchannel)(struct rpmsg_endpoint *ept, u32 src, u32
> > dst,
> > +			     void *data, int len);
> > +
> > +	int (*announce_create)(struct rpmsg_device *ept);
> > +	int (*announce_destroy)(struct rpmsg_device *ept);
> > +};
> It will be nice to document if ops are mandatory or optional.
> 

I'll break them out in a ops struct and throw in some kerneldoc in both
cases.

Thanks for the feedback!

Regards,
Bjorn

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 06/14] rpmsg: Indirect all virtio related function calls
@ 2016-08-18 18:13       ` Bjorn Andersson
  0 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-18 18:13 UTC (permalink / raw)
  To: Loic PALLARDY
  Cc: Ohad Ben-Cohen, linux-arm-msm, linux-remoteproc, linux-kernel,
	linux-arm-kernel

On Thu 18 Aug 05:14 PDT 2016, Loic PALLARDY wrote:

> > diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c
[..]
> >  struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev,
> >  					rpmsg_rx_cb_t cb, void *priv, u32
> > addr)
> >  {
> > -	return __rpmsg_create_ept(rpdev->vrp, rpdev, cb, priv, addr);
> > +	return rpdev->create_ept(rpdev, cb, priv, addr);
> Hi Bjorn,
> 
> It will be good to test if pointer is valid before calling function.
> 

Per the rpmsg_send() implementation, I can make it loud but friendlier
by:

if (WARN_ON(!rpdev))
	return -EINVAL;

[..]
> > 
> > +static const struct rpmsg_device virtio_rpmsg_ops = {
> > +	.create_ept = virtio_rpmsg_create_ept,
> > +	.destroy_ept = virtio_rpmsg_destroy_ept,
> > +	.send = virtio_rpmsg_send,
> > +	.sendto = virtio_rpmsg_sendto,
> > +	.send_offchannel = virtio_rpmsg_send_offchannel,
> > +	.trysend = virtio_rpmsg_trysend,
> > +	.trysendto = virtio_rpmsg_trysendto,
> > +	.trysend_offchannel = virtio_rpmsg_trysend_offchannel,
> > +	.announce_create = virtio_rpmsg_announce_create,
> > +	.announce_destroy = virtio_rpmsg_announce_destroy,
> > +};
> Why not creating a dedicated ops struct like other framework?
> Here ops are mixed with other parameters.
> 

That's a good suggestion...

> > +
> >  /*
> >   * create an rpmsg channel using its name and address info.
> >   * this function will be used to create both static and dynamic
> > @@ -511,6 +568,9 @@ static struct rpmsg_device
> > *rpmsg_create_channel(struct virtproc_info *vrp,
> >  	if (!rpdev)
> >  		return NULL;
> > 
> > +	/* Assign callbacks for rpmsg_channel */
> > +	*rpdev = virtio_rpmsg_ops;
> It is not a simple affectation behind this operation, more a memcopy of the complete struct.
> Not easy to read from my pov.

...and would clean this up. I'll do that.

> > +
> >  	rpdev->vrp = vrp;
> >  	rpdev->src = chinfo->src;
> >  	rpdev->dst = chinfo->dst;
> > @@ -793,11 +853,17 @@ out:
> >  int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
> >  {
> >  	struct rpmsg_device *rpdev = ept->rpdev;
> > +
> > +	return rpdev->send(ept, data, len);
> Test pointer before using it

Yeah, this would follow from the earlier patch.

> 
> > +}
> > +
[..]
> > diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
[..]
> > u32);
> > +	struct rpmsg_endpoint *(*create_ept)(struct rpmsg_device *rpdev,
> > +					    rpmsg_rx_cb_t cb, void *priv, u32
> > addr);
> > +	void (*destroy_ept)(struct rpmsg_endpoint *ept);
> > +
> > +	int (*send)(struct rpmsg_endpoint *ept, void *data, int len);
> > +	int (*sendto)(struct rpmsg_endpoint *ept, void *data, int len, u32
> > dst);
> > +	int (*send_offchannel)(struct rpmsg_endpoint *ept, u32 src, u32 dst,
> > +				  void *data, int len);
> > +
> > +	int (*trysend)(struct rpmsg_endpoint *ept, void *data, int len);
> > +	int (*trysendto)(struct rpmsg_endpoint *ept, void *data, int len, u32
> > dst);
> > +	int (*trysend_offchannel)(struct rpmsg_endpoint *ept, u32 src, u32
> > dst,
> > +			     void *data, int len);
> > +
> > +	int (*announce_create)(struct rpmsg_device *ept);
> > +	int (*announce_destroy)(struct rpmsg_device *ept);
> > +};
> It will be nice to document if ops are mandatory or optional.
> 

I'll break them out in a ops struct and throw in some kerneldoc in both
cases.

Thanks for the feedback!

Regards,
Bjorn

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH 06/14] rpmsg: Indirect all virtio related function calls
@ 2016-08-18 18:13       ` Bjorn Andersson
  0 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-18 18:13 UTC (permalink / raw)
  To: Loic PALLARDY
  Cc: Ohad Ben-Cohen, linux-remoteproc, linux-arm-msm,
	linux-arm-kernel, linux-kernel

On Thu 18 Aug 05:14 PDT 2016, Loic PALLARDY wrote:

> > diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c
[..]
> >  struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev,
> >  					rpmsg_rx_cb_t cb, void *priv, u32
> > addr)
> >  {
> > -	return __rpmsg_create_ept(rpdev->vrp, rpdev, cb, priv, addr);
> > +	return rpdev->create_ept(rpdev, cb, priv, addr);
> Hi Bjorn,
> 
> It will be good to test if pointer is valid before calling function.
> 

Per the rpmsg_send() implementation, I can make it loud but friendlier
by:

if (WARN_ON(!rpdev))
	return -EINVAL;

[..]
> > 
> > +static const struct rpmsg_device virtio_rpmsg_ops = {
> > +	.create_ept = virtio_rpmsg_create_ept,
> > +	.destroy_ept = virtio_rpmsg_destroy_ept,
> > +	.send = virtio_rpmsg_send,
> > +	.sendto = virtio_rpmsg_sendto,
> > +	.send_offchannel = virtio_rpmsg_send_offchannel,
> > +	.trysend = virtio_rpmsg_trysend,
> > +	.trysendto = virtio_rpmsg_trysendto,
> > +	.trysend_offchannel = virtio_rpmsg_trysend_offchannel,
> > +	.announce_create = virtio_rpmsg_announce_create,
> > +	.announce_destroy = virtio_rpmsg_announce_destroy,
> > +};
> Why not creating a dedicated ops struct like other framework?
> Here ops are mixed with other parameters.
> 

That's a good suggestion...

> > +
> >  /*
> >   * create an rpmsg channel using its name and address info.
> >   * this function will be used to create both static and dynamic
> > @@ -511,6 +568,9 @@ static struct rpmsg_device
> > *rpmsg_create_channel(struct virtproc_info *vrp,
> >  	if (!rpdev)
> >  		return NULL;
> > 
> > +	/* Assign callbacks for rpmsg_channel */
> > +	*rpdev = virtio_rpmsg_ops;
> It is not a simple affectation behind this operation, more a memcopy of the complete struct.
> Not easy to read from my pov.

...and would clean this up. I'll do that.

> > +
> >  	rpdev->vrp = vrp;
> >  	rpdev->src = chinfo->src;
> >  	rpdev->dst = chinfo->dst;
> > @@ -793,11 +853,17 @@ out:
> >  int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
> >  {
> >  	struct rpmsg_device *rpdev = ept->rpdev;
> > +
> > +	return rpdev->send(ept, data, len);
> Test pointer before using it

Yeah, this would follow from the earlier patch.

> 
> > +}
> > +
[..]
> > diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
[..]
> > u32);
> > +	struct rpmsg_endpoint *(*create_ept)(struct rpmsg_device *rpdev,
> > +					    rpmsg_rx_cb_t cb, void *priv, u32
> > addr);
> > +	void (*destroy_ept)(struct rpmsg_endpoint *ept);
> > +
> > +	int (*send)(struct rpmsg_endpoint *ept, void *data, int len);
> > +	int (*sendto)(struct rpmsg_endpoint *ept, void *data, int len, u32
> > dst);
> > +	int (*send_offchannel)(struct rpmsg_endpoint *ept, u32 src, u32 dst,
> > +				  void *data, int len);
> > +
> > +	int (*trysend)(struct rpmsg_endpoint *ept, void *data, int len);
> > +	int (*trysendto)(struct rpmsg_endpoint *ept, void *data, int len, u32
> > dst);
> > +	int (*trysend_offchannel)(struct rpmsg_endpoint *ept, u32 src, u32
> > dst,
> > +			     void *data, int len);
> > +
> > +	int (*announce_create)(struct rpmsg_device *ept);
> > +	int (*announce_destroy)(struct rpmsg_device *ept);
> > +};
> It will be nice to document if ops are mandatory or optional.
> 

I'll break them out in a ops struct and throw in some kerneldoc in both
cases.

Thanks for the feedback!

Regards,
Bjorn

^ permalink raw reply	[flat|nested] 54+ messages in thread

* [PATCH 06/14] rpmsg: Indirect all virtio related function calls
@ 2016-08-18 18:13       ` Bjorn Andersson
  0 siblings, 0 replies; 54+ messages in thread
From: Bjorn Andersson @ 2016-08-18 18:13 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu 18 Aug 05:14 PDT 2016, Loic PALLARDY wrote:

> > diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c
[..]
> >  struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev,
> >  					rpmsg_rx_cb_t cb, void *priv, u32
> > addr)
> >  {
> > -	return __rpmsg_create_ept(rpdev->vrp, rpdev, cb, priv, addr);
> > +	return rpdev->create_ept(rpdev, cb, priv, addr);
> Hi Bjorn,
> 
> It will be good to test if pointer is valid before calling function.
> 

Per the rpmsg_send() implementation, I can make it loud but friendlier
by:

if (WARN_ON(!rpdev))
	return -EINVAL;

[..]
> > 
> > +static const struct rpmsg_device virtio_rpmsg_ops = {
> > +	.create_ept = virtio_rpmsg_create_ept,
> > +	.destroy_ept = virtio_rpmsg_destroy_ept,
> > +	.send = virtio_rpmsg_send,
> > +	.sendto = virtio_rpmsg_sendto,
> > +	.send_offchannel = virtio_rpmsg_send_offchannel,
> > +	.trysend = virtio_rpmsg_trysend,
> > +	.trysendto = virtio_rpmsg_trysendto,
> > +	.trysend_offchannel = virtio_rpmsg_trysend_offchannel,
> > +	.announce_create = virtio_rpmsg_announce_create,
> > +	.announce_destroy = virtio_rpmsg_announce_destroy,
> > +};
> Why not creating a dedicated ops struct like other framework?
> Here ops are mixed with other parameters.
> 

That's a good suggestion...

> > +
> >  /*
> >   * create an rpmsg channel using its name and address info.
> >   * this function will be used to create both static and dynamic
> > @@ -511,6 +568,9 @@ static struct rpmsg_device
> > *rpmsg_create_channel(struct virtproc_info *vrp,
> >  	if (!rpdev)
> >  		return NULL;
> > 
> > +	/* Assign callbacks for rpmsg_channel */
> > +	*rpdev = virtio_rpmsg_ops;
> It is not a simple affectation behind this operation, more a memcopy of the complete struct.
> Not easy to read from my pov.

...and would clean this up. I'll do that.

> > +
> >  	rpdev->vrp = vrp;
> >  	rpdev->src = chinfo->src;
> >  	rpdev->dst = chinfo->dst;
> > @@ -793,11 +853,17 @@ out:
> >  int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
> >  {
> >  	struct rpmsg_device *rpdev = ept->rpdev;
> > +
> > +	return rpdev->send(ept, data, len);
> Test pointer before using it

Yeah, this would follow from the earlier patch.

> 
> > +}
> > +
[..]
> > diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
[..]
> > u32);
> > +	struct rpmsg_endpoint *(*create_ept)(struct rpmsg_device *rpdev,
> > +					    rpmsg_rx_cb_t cb, void *priv, u32
> > addr);
> > +	void (*destroy_ept)(struct rpmsg_endpoint *ept);
> > +
> > +	int (*send)(struct rpmsg_endpoint *ept, void *data, int len);
> > +	int (*sendto)(struct rpmsg_endpoint *ept, void *data, int len, u32
> > dst);
> > +	int (*send_offchannel)(struct rpmsg_endpoint *ept, u32 src, u32 dst,
> > +				  void *data, int len);
> > +
> > +	int (*trysend)(struct rpmsg_endpoint *ept, void *data, int len);
> > +	int (*trysendto)(struct rpmsg_endpoint *ept, void *data, int len, u32
> > dst);
> > +	int (*trysend_offchannel)(struct rpmsg_endpoint *ept, u32 src, u32
> > dst,
> > +			     void *data, int len);
> > +
> > +	int (*announce_create)(struct rpmsg_device *ept);
> > +	int (*announce_destroy)(struct rpmsg_device *ept);
> > +};
> It will be nice to document if ops are mandatory or optional.
> 

I'll break them out in a ops struct and throw in some kerneldoc in both
cases.

Thanks for the feedback!

Regards,
Bjorn

^ permalink raw reply	[flat|nested] 54+ messages in thread

end of thread, other threads:[~2016-08-19  1:37 UTC | newest]

Thread overview: 54+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-08-16  0:17 [PATCH 00/14] Split rpmsg into a framework Bjorn Andersson
2016-08-16  0:17 ` Bjorn Andersson
2016-08-16  0:17 ` [PATCH 01/14] rpmsg: Enable matching devices with drivers based on DT Bjorn Andersson
2016-08-16  0:17   ` Bjorn Andersson
2016-08-16  0:17   ` Bjorn Andersson
2016-08-16  0:17 ` [PATCH 02/14] rpmsg: Name rpmsg devices based on channel id Bjorn Andersson
2016-08-16  0:17   ` Bjorn Andersson
2016-08-16  0:17 ` [PATCH 03/14] rpmsg: rpmsg_send() operations takes rpmsg_endpoint Bjorn Andersson
2016-08-16  0:17   ` Bjorn Andersson
2016-08-16  0:17   ` Bjorn Andersson
2016-08-18  7:36   ` Loic PALLARDY
2016-08-18  7:36     ` Loic PALLARDY
2016-08-18  7:36     ` Loic PALLARDY
2016-08-18 18:04     ` Bjorn Andersson
2016-08-18 18:04       ` Bjorn Andersson
2016-08-18 18:04       ` Bjorn Andersson
2016-08-18 18:04       ` Bjorn Andersson
2016-08-16  0:17 ` [PATCH 04/14] rpmsg: Internalize rpmsg_send() implementations Bjorn Andersson
2016-08-16  0:17   ` Bjorn Andersson
2016-08-16  0:17   ` Bjorn Andersson
2016-08-16  0:17 ` [PATCH 05/14] rpmsg: Unify rpmsg device vs channel naming Bjorn Andersson
2016-08-16  0:17   ` Bjorn Andersson
2016-08-16  0:17 ` [PATCH 06/14] rpmsg: Indirect all virtio related function calls Bjorn Andersson
2016-08-16  0:17   ` Bjorn Andersson
2016-08-18 12:14   ` Loic PALLARDY
2016-08-18 12:14     ` Loic PALLARDY
2016-08-18 12:14     ` Loic PALLARDY
2016-08-18 18:13     ` Bjorn Andersson
2016-08-18 18:13       ` Bjorn Andersson
2016-08-18 18:13       ` Bjorn Andersson
2016-08-18 18:13       ` Bjorn Andersson
2016-08-16  0:17 ` [PATCH 07/14] rpmsg: Split off generic tail of create_channel() Bjorn Andersson
2016-08-16  0:17   ` Bjorn Andersson
2016-08-16  0:17 ` [PATCH 08/14] rpmsg: Split rpmsg core and virtio backend Bjorn Andersson
2016-08-16  0:17   ` Bjorn Andersson
2016-08-18 11:59   ` Loic PALLARDY
2016-08-18 11:59     ` Loic PALLARDY
2016-08-18 11:59     ` Loic PALLARDY
2016-08-18 18:09     ` Bjorn Andersson
2016-08-18 18:09       ` Bjorn Andersson
2016-08-18 18:09       ` Bjorn Andersson
2016-08-18 18:09       ` Bjorn Andersson
2016-08-16  0:17 ` [PATCH 09/14] rpmsg: Internalize rpmsg core ops Bjorn Andersson
2016-08-16  0:17   ` Bjorn Andersson
2016-08-16  0:17 ` [PATCH 10/14] rpmsg: virtio: Internalize vrp pointer Bjorn Andersson
2016-08-16  0:17   ` Bjorn Andersson
2016-08-16  0:17 ` [PATCH 11/14] rpmsg: Move virtio specifics from public header Bjorn Andersson
2016-08-16  0:17   ` Bjorn Andersson
2016-08-16  0:17 ` [PATCH 12/14] rpmsg: Make rpmsg_create_ept() take channel_info struct Bjorn Andersson
2016-08-16  0:17   ` Bjorn Andersson
2016-08-16  0:17 ` [PATCH 13/14] rpmsg: Allow callback to return errors Bjorn Andersson
2016-08-16  0:17   ` Bjorn Andersson
2016-08-16  0:17 ` [PATCH 14/14] rpmsg: Introduce Qualcomm SMD backend Bjorn Andersson
2016-08-16  0:17   ` Bjorn Andersson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.