All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/17] Make rpmsg a framework
@ 2016-09-01 22:27 ` Bjorn Andersson
  0 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:27 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.


Changes from v1:
- Split up the patch moving core code to rpmsg_core into several commits
- Dropped the wrapping struct in rpmsg_core and just added the ops to the
  public API (but hid the implementation details)
- Reordered things to reduce the size of the later patches

Bjorn Andersson (17):
  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: Make rpmsg_create_ept() take channel_info struct
  rpmsg: Clean up rpmsg device vs channel naming
  rpmsg: Introduce indirection table for rpmsg_device operations
  rpmsg: Move rpmsg_device API to new file
  rpmsg: Indirection table for rpmsg_endpoint operations
  rpmsg: Move endpoint related interface to rpmsg core
  rpmsg: Move helper for finding rpmsg devices to core
  rpmsg: Split off generic tail of create_channel()
  rpmsg: Split rpmsg core and virtio backend
  rpmsg: Hide rpmsg indirection tables
  rpmsg: virtio: Hide vrp pointer from the public API
  rpmsg: Move virtio specifics from public header
  rpmsg: Allow callback to return errors
  rpmsg: Introduce Qualcomm SMD backend

 drivers/remoteproc/Kconfig          |    4 +-
 drivers/rpmsg/Kconfig               |   14 +
 drivers/rpmsg/Makefile              |    4 +-
 drivers/rpmsg/qcom_smd.c            | 1434 +++++++++++++++++++++++++++++++++++
 drivers/rpmsg/rpmsg_core.c          |  498 ++++++++++++
 drivers/rpmsg/rpmsg_internal.h      |   82 ++
 drivers/rpmsg/virtio_rpmsg_bus.c    |  487 +++++-------
 include/linux/rpmsg.h               |  246 +-----
 samples/rpmsg/rpmsg_client_sample.c |   14 +-
 9 files changed, 2266 insertions(+), 517 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] 68+ messages in thread

* [PATCH v2 00/17] Make rpmsg a framework
@ 2016-09-01 22:27 ` Bjorn Andersson
  0 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:27 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.


Changes from v1:
- Split up the patch moving core code to rpmsg_core into several commits
- Dropped the wrapping struct in rpmsg_core and just added the ops to the
  public API (but hid the implementation details)
- Reordered things to reduce the size of the later patches

Bjorn Andersson (17):
  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: Make rpmsg_create_ept() take channel_info struct
  rpmsg: Clean up rpmsg device vs channel naming
  rpmsg: Introduce indirection table for rpmsg_device operations
  rpmsg: Move rpmsg_device API to new file
  rpmsg: Indirection table for rpmsg_endpoint operations
  rpmsg: Move endpoint related interface to rpmsg core
  rpmsg: Move helper for finding rpmsg devices to core
  rpmsg: Split off generic tail of create_channel()
  rpmsg: Split rpmsg core and virtio backend
  rpmsg: Hide rpmsg indirection tables
  rpmsg: virtio: Hide vrp pointer from the public API
  rpmsg: Move virtio specifics from public header
  rpmsg: Allow callback to return errors
  rpmsg: Introduce Qualcomm SMD backend

 drivers/remoteproc/Kconfig          |    4 +-
 drivers/rpmsg/Kconfig               |   14 +
 drivers/rpmsg/Makefile              |    4 +-
 drivers/rpmsg/qcom_smd.c            | 1434 +++++++++++++++++++++++++++++++++++
 drivers/rpmsg/rpmsg_core.c          |  498 ++++++++++++
 drivers/rpmsg/rpmsg_internal.h      |   82 ++
 drivers/rpmsg/virtio_rpmsg_bus.c    |  487 +++++-------
 include/linux/rpmsg.h               |  246 +-----
 samples/rpmsg/rpmsg_client_sample.c |   14 +-
 9 files changed, 2266 insertions(+), 517 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] 68+ messages in thread

* [PATCH v2 01/17] rpmsg: Enable matching devices with drivers based on DT
  2016-09-01 22:27 ` Bjorn Andersson
  (?)
@ 2016-09-01 22:27   ` Bjorn Andersson
  -1 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:27 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>
---

Changes since v1:
- None

 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] 68+ messages in thread

* [PATCH v2 01/17] rpmsg: Enable matching devices with drivers based on DT
@ 2016-09-01 22:27   ` Bjorn Andersson
  0 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:27 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>
---

Changes since v1:
- None

 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] 68+ messages in thread

* [PATCH v2 01/17] rpmsg: Enable matching devices with drivers based on DT
@ 2016-09-01 22:27   ` Bjorn Andersson
  0 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:27 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>
---

Changes since v1:
- None

 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] 68+ messages in thread

* [PATCH v2 02/17] rpmsg: Name rpmsg devices based on channel id
  2016-09-01 22:27 ` Bjorn Andersson
  (?)
@ 2016-09-01 22:27   ` Bjorn Andersson
  -1 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:27 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>
---

Changes since v1:
- None

 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] 68+ messages in thread

* [PATCH v2 02/17] rpmsg: Name rpmsg devices based on channel id
@ 2016-09-01 22:27   ` Bjorn Andersson
  0 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:27 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson
  Cc: linux-arm-msm, linux-remoteproc, linux-kernel, 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>
---

Changes since v1:
- None

 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] 68+ messages in thread

* [PATCH v2 02/17] rpmsg: Name rpmsg devices based on channel id
@ 2016-09-01 22:27   ` Bjorn Andersson
  0 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:27 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>
---

Changes since v1:
- None

 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] 68+ messages in thread

* [PATCH v2 03/17] rpmsg: rpmsg_send() operations takes rpmsg_endpoint
  2016-09-01 22:27 ` Bjorn Andersson
@ 2016-09-01 22:27   ` Bjorn Andersson
  -1 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:27 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>
---

Changes since v1:
- Announcing the primary endpoint's address rather then the rpdev

 drivers/rpmsg/virtio_rpmsg_bus.c    |  6 ++--
 include/linux/rpmsg.h               | 70 +++++++++++++++++++++----------------
 samples/rpmsg/rpmsg_client_sample.c |  4 +--
 3 files changed, 45 insertions(+), 35 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index c4bd89ea7681..345036b485d7 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -379,10 +379,10 @@ static int rpmsg_dev_probe(struct device *dev)
 		struct rpmsg_ns_msg nsm;
 
 		strncpy(nsm.name, rpdev->id.name, RPMSG_NAME_SIZE);
-		nsm.addr = rpdev->src;
+		nsm.addr = rpdev->ept->addr;
 		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..a901a331a190 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 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.
  *
@@ -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);
 }
 
diff --git a/samples/rpmsg/rpmsg_client_sample.c b/samples/rpmsg/rpmsg_client_sample.c
index 7e17d1c0aaf2..37975eddd64e 100644
--- a/samples/rpmsg/rpmsg_client_sample.c
+++ b/samples/rpmsg/rpmsg_client_sample.c
@@ -47,7 +47,7 @@ static void rpmsg_sample_cb(struct rpmsg_channel *rpdev, void *data, int len,
 	}
 
 	/* send a new message now */
-	ret = rpmsg_send(rpdev, MSG, strlen(MSG));
+	ret = rpmsg_send(rpdev->ept, MSG, strlen(MSG));
 	if (ret)
 		dev_err(&rpdev->dev, "rpmsg_send failed: %d\n", ret);
 }
@@ -67,7 +67,7 @@ static int rpmsg_sample_probe(struct rpmsg_channel *rpdev)
 	dev_set_drvdata(&rpdev->dev, idata);
 
 	/* send a message to our remote processor */
-	ret = rpmsg_send(rpdev, MSG, strlen(MSG));
+	ret = rpmsg_send(rpdev->ept, MSG, strlen(MSG));
 	if (ret) {
 		dev_err(&rpdev->dev, "rpmsg_send failed: %d\n", ret);
 		return ret;
-- 
2.5.0

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

* [PATCH v2 03/17] rpmsg: rpmsg_send() operations takes rpmsg_endpoint
@ 2016-09-01 22:27   ` Bjorn Andersson
  0 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:27 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>
---

Changes since v1:
- Announcing the primary endpoint's address rather then the rpdev

 drivers/rpmsg/virtio_rpmsg_bus.c    |  6 ++--
 include/linux/rpmsg.h               | 70 +++++++++++++++++++++----------------
 samples/rpmsg/rpmsg_client_sample.c |  4 +--
 3 files changed, 45 insertions(+), 35 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index c4bd89ea7681..345036b485d7 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -379,10 +379,10 @@ static int rpmsg_dev_probe(struct device *dev)
 		struct rpmsg_ns_msg nsm;
 
 		strncpy(nsm.name, rpdev->id.name, RPMSG_NAME_SIZE);
-		nsm.addr = rpdev->src;
+		nsm.addr = rpdev->ept->addr;
 		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..a901a331a190 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 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.
  *
@@ -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);
 }
 
diff --git a/samples/rpmsg/rpmsg_client_sample.c b/samples/rpmsg/rpmsg_client_sample.c
index 7e17d1c0aaf2..37975eddd64e 100644
--- a/samples/rpmsg/rpmsg_client_sample.c
+++ b/samples/rpmsg/rpmsg_client_sample.c
@@ -47,7 +47,7 @@ static void rpmsg_sample_cb(struct rpmsg_channel *rpdev, void *data, int len,
 	}
 
 	/* send a new message now */
-	ret = rpmsg_send(rpdev, MSG, strlen(MSG));
+	ret = rpmsg_send(rpdev->ept, MSG, strlen(MSG));
 	if (ret)
 		dev_err(&rpdev->dev, "rpmsg_send failed: %d\n", ret);
 }
@@ -67,7 +67,7 @@ static int rpmsg_sample_probe(struct rpmsg_channel *rpdev)
 	dev_set_drvdata(&rpdev->dev, idata);
 
 	/* send a message to our remote processor */
-	ret = rpmsg_send(rpdev, MSG, strlen(MSG));
+	ret = rpmsg_send(rpdev->ept, MSG, strlen(MSG));
 	if (ret) {
 		dev_err(&rpdev->dev, "rpmsg_send failed: %d\n", ret);
 		return ret;
-- 
2.5.0

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

* [PATCH v2 04/17] rpmsg: Make rpmsg_create_ept() take channel_info struct
  2016-09-01 22:27 ` Bjorn Andersson
  (?)
@ 2016-09-01 22:27   ` Bjorn Andersson
  -1 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:27 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson
  Cc: linux-remoteproc, linux-arm-msm, linux-arm-kernel, linux-kernel

As we introduce support for additional rpmsg backends, some of these
only supports 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>
---

Changes since v1:
- None

 drivers/rpmsg/virtio_rpmsg_bus.c | 26 ++++++++++----------------
 include/linux/rpmsg.h            | 15 ++++++++++++++-
 2 files changed, 24 insertions(+), 17 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 345036b485d7..7c7c6a8b21d9 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -73,18 +73,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_channel(d) container_of(d, struct rpmsg_channel, dev)
 #define to_rpmsg_driver(d) container_of(d, struct rpmsg_driver, drv)
 
@@ -259,7 +247,7 @@ free_ept:
  * @rpdev: rpmsg channel device
  * @cb: rx callback handler
  * @priv: private data for the driver's use
- * @addr: local rpmsg address to bind with @cb
+ * @chinfo: channel_info with the 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
@@ -295,9 +283,10 @@ free_ept:
  * Returns a pointer to the endpoint on success, or NULL on error.
  */
 struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_channel *rpdev,
-					rpmsg_rx_cb_t cb, void *priv, u32 addr)
+					rpmsg_rx_cb_t cb, void *priv,
+					struct rpmsg_channel_info chinfo)
 {
-	return __rpmsg_create_ept(rpdev->vrp, rpdev, cb, priv, addr);
+	return __rpmsg_create_ept(rpdev->vrp, rpdev, cb, priv, chinfo.src);
 }
 EXPORT_SYMBOL(rpmsg_create_ept);
 
@@ -353,10 +342,15 @@ static int rpmsg_dev_probe(struct device *dev)
 	struct rpmsg_channel *rpdev = to_rpmsg_channel(dev);
 	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
 	struct virtproc_info *vrp = rpdev->vrp;
+	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/include/linux/rpmsg.h b/include/linux/rpmsg.h
index a901a331a190..f278407fcf48 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -98,6 +98,18 @@ enum rpmsg_ns_flags {
 struct virtproc_info;
 
 /**
+ * struct rpmsg_channel_info - 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_channel - devices that belong to the rpmsg bus are called channels
  * @vrp: the remote processor this channel belongs to
  * @dev: the device struct
@@ -171,7 +183,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_channel *,
-					rpmsg_rx_cb_t cb, void *priv, u32 addr);
+					rpmsg_rx_cb_t cb, void *priv,
+					struct rpmsg_channel_info chinfo);
 int
 rpmsg_send_offchannel_raw(struct rpmsg_channel *, u32, u32, void *, int, bool);
 
-- 
2.5.0

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

* [PATCH v2 04/17] rpmsg: Make rpmsg_create_ept() take channel_info struct
@ 2016-09-01 22:27   ` Bjorn Andersson
  0 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:27 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson
  Cc: linux-arm-msm, linux-remoteproc, linux-kernel, linux-arm-kernel

As we introduce support for additional rpmsg backends, some of these
only supports 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>
---

Changes since v1:
- None

 drivers/rpmsg/virtio_rpmsg_bus.c | 26 ++++++++++----------------
 include/linux/rpmsg.h            | 15 ++++++++++++++-
 2 files changed, 24 insertions(+), 17 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 345036b485d7..7c7c6a8b21d9 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -73,18 +73,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_channel(d) container_of(d, struct rpmsg_channel, dev)
 #define to_rpmsg_driver(d) container_of(d, struct rpmsg_driver, drv)
 
@@ -259,7 +247,7 @@ free_ept:
  * @rpdev: rpmsg channel device
  * @cb: rx callback handler
  * @priv: private data for the driver's use
- * @addr: local rpmsg address to bind with @cb
+ * @chinfo: channel_info with the 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
@@ -295,9 +283,10 @@ free_ept:
  * Returns a pointer to the endpoint on success, or NULL on error.
  */
 struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_channel *rpdev,
-					rpmsg_rx_cb_t cb, void *priv, u32 addr)
+					rpmsg_rx_cb_t cb, void *priv,
+					struct rpmsg_channel_info chinfo)
 {
-	return __rpmsg_create_ept(rpdev->vrp, rpdev, cb, priv, addr);
+	return __rpmsg_create_ept(rpdev->vrp, rpdev, cb, priv, chinfo.src);
 }
 EXPORT_SYMBOL(rpmsg_create_ept);
 
@@ -353,10 +342,15 @@ static int rpmsg_dev_probe(struct device *dev)
 	struct rpmsg_channel *rpdev = to_rpmsg_channel(dev);
 	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
 	struct virtproc_info *vrp = rpdev->vrp;
+	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/include/linux/rpmsg.h b/include/linux/rpmsg.h
index a901a331a190..f278407fcf48 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -98,6 +98,18 @@ enum rpmsg_ns_flags {
 struct virtproc_info;
 
 /**
+ * struct rpmsg_channel_info - 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_channel - devices that belong to the rpmsg bus are called channels
  * @vrp: the remote processor this channel belongs to
  * @dev: the device struct
@@ -171,7 +183,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_channel *,
-					rpmsg_rx_cb_t cb, void *priv, u32 addr);
+					rpmsg_rx_cb_t cb, void *priv,
+					struct rpmsg_channel_info chinfo);
 int
 rpmsg_send_offchannel_raw(struct rpmsg_channel *, u32, u32, void *, int, bool);
 
-- 
2.5.0

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

* [PATCH v2 04/17] rpmsg: Make rpmsg_create_ept() take channel_info struct
@ 2016-09-01 22:27   ` Bjorn Andersson
  0 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:27 UTC (permalink / raw)
  To: linux-arm-kernel

As we introduce support for additional rpmsg backends, some of these
only supports 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>
---

Changes since v1:
- None

 drivers/rpmsg/virtio_rpmsg_bus.c | 26 ++++++++++----------------
 include/linux/rpmsg.h            | 15 ++++++++++++++-
 2 files changed, 24 insertions(+), 17 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 345036b485d7..7c7c6a8b21d9 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -73,18 +73,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_channel(d) container_of(d, struct rpmsg_channel, dev)
 #define to_rpmsg_driver(d) container_of(d, struct rpmsg_driver, drv)
 
@@ -259,7 +247,7 @@ free_ept:
  * @rpdev: rpmsg channel device
  * @cb: rx callback handler
  * @priv: private data for the driver's use
- * @addr: local rpmsg address to bind with @cb
+ * @chinfo: channel_info with the 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
@@ -295,9 +283,10 @@ free_ept:
  * Returns a pointer to the endpoint on success, or NULL on error.
  */
 struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_channel *rpdev,
-					rpmsg_rx_cb_t cb, void *priv, u32 addr)
+					rpmsg_rx_cb_t cb, void *priv,
+					struct rpmsg_channel_info chinfo)
 {
-	return __rpmsg_create_ept(rpdev->vrp, rpdev, cb, priv, addr);
+	return __rpmsg_create_ept(rpdev->vrp, rpdev, cb, priv, chinfo.src);
 }
 EXPORT_SYMBOL(rpmsg_create_ept);
 
@@ -353,10 +342,15 @@ static int rpmsg_dev_probe(struct device *dev)
 	struct rpmsg_channel *rpdev = to_rpmsg_channel(dev);
 	struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpdev->dev.driver);
 	struct virtproc_info *vrp = rpdev->vrp;
+	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/include/linux/rpmsg.h b/include/linux/rpmsg.h
index a901a331a190..f278407fcf48 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -98,6 +98,18 @@ enum rpmsg_ns_flags {
 struct virtproc_info;
 
 /**
+ * struct rpmsg_channel_info - 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_channel - devices that belong to the rpmsg bus are called channels
  * @vrp: the remote processor this channel belongs to
  * @dev: the device struct
@@ -171,7 +183,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_channel *,
-					rpmsg_rx_cb_t cb, void *priv, u32 addr);
+					rpmsg_rx_cb_t cb, void *priv,
+					struct rpmsg_channel_info chinfo);
 int
 rpmsg_send_offchannel_raw(struct rpmsg_channel *, u32, u32, void *, int, bool);
 
-- 
2.5.0

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

* [PATCH v2 05/17] rpmsg: Clean up rpmsg device vs channel naming
  2016-09-01 22:27 ` Bjorn Andersson
  (?)
@ 2016-09-01 22:27   ` Bjorn Andersson
  -1 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:27 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, with the communication happening
on endpoints it's clearer to just call this a "device" in a public API.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---

Changes since v1:
- None

 drivers/rpmsg/virtio_rpmsg_bus.c    | 42 ++++++++++++++++++-------------------
 include/linux/rpmsg.h               | 32 +++++++++++++++-------------
 samples/rpmsg/rpmsg_client_sample.c |  6 +++---
 3 files changed, 41 insertions(+), 39 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 7c7c6a8b21d9..1ac9fd871760 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -73,7 +73,7 @@ struct virtproc_info {
 	struct rpmsg_endpoint *ns_ept;
 };
 
-#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)
 
 /*
@@ -113,7 +113,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);		\
 }
@@ -127,7 +127,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);
 }
@@ -142,7 +142,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;
@@ -151,7 +151,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;
@@ -166,7 +166,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);
@@ -194,7 +194,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)
 {
@@ -282,7 +282,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,
 					struct rpmsg_channel_info chinfo)
 {
@@ -339,7 +339,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_channel_info chinfo = {};
@@ -387,7 +387,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;
@@ -451,7 +451,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);
 }
@@ -461,10 +461,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;
@@ -484,15 +484,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);
@@ -544,7 +544,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;
 
@@ -669,7 +669,7 @@ 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,
+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;
@@ -879,11 +879,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 f278407fcf48..35a0f39fd09b 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -110,7 +110,7 @@ struct rpmsg_channel_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)
@@ -119,7 +119,7 @@ struct rpmsg_channel_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;
@@ -129,7 +129,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
@@ -155,7 +155,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;
@@ -174,19 +174,21 @@ 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,
 					struct rpmsg_channel_info chinfo);
 int
-rpmsg_send_offchannel_raw(struct rpmsg_channel *, u32, u32, void *, int, bool);
+rpmsg_send_offchannel_raw(struct rpmsg_device *, u32, u32, void *, int, bool);
 
 /* use a macro to avoid include chaining to get THIS_MODULE */
 #define register_rpmsg_driver(drv) \
@@ -224,7 +226,7 @@ rpmsg_send_offchannel_raw(struct rpmsg_channel *, u32, u32, void *, int, bool);
  */
 static inline 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);
@@ -251,7 +253,7 @@ static inline int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
 static inline
 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);
@@ -281,7 +283,7 @@ static inline
 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);
 }
@@ -306,7 +308,7 @@ int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
 static inline
 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);
@@ -332,7 +334,7 @@ int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
 static inline
 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);
@@ -361,7 +363,7 @@ static inline
 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);
 }
diff --git a/samples/rpmsg/rpmsg_client_sample.c b/samples/rpmsg/rpmsg_client_sample.c
index 37975eddd64e..4fcd7ee13fb9 100644
--- a/samples/rpmsg/rpmsg_client_sample.c
+++ b/samples/rpmsg/rpmsg_client_sample.c
@@ -28,7 +28,7 @@ struct instance_data {
 	int rx_count;
 };
 
-static void rpmsg_sample_cb(struct rpmsg_channel *rpdev, void *data, int len,
+static void rpmsg_sample_cb(struct rpmsg_device *rpdev, void *data, int len,
 						void *priv, u32 src)
 {
 	int ret;
@@ -52,7 +52,7 @@ static void rpmsg_sample_cb(struct rpmsg_channel *rpdev, void *data, int len,
 		dev_err(&rpdev->dev, "rpmsg_send failed: %d\n", ret);
 }
 
-static int rpmsg_sample_probe(struct rpmsg_channel *rpdev)
+static int rpmsg_sample_probe(struct rpmsg_device *rpdev)
 {
 	int ret;
 	struct instance_data *idata;
@@ -76,7 +76,7 @@ static int rpmsg_sample_probe(struct rpmsg_channel *rpdev)
 	return 0;
 }
 
-static void rpmsg_sample_remove(struct rpmsg_channel *rpdev)
+static void rpmsg_sample_remove(struct rpmsg_device *rpdev)
 {
 	dev_info(&rpdev->dev, "rpmsg sample client driver is removed\n");
 }
-- 
2.5.0

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

* [PATCH v2 05/17] rpmsg: Clean up rpmsg device vs channel naming
@ 2016-09-01 22:27   ` Bjorn Andersson
  0 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:27 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson
  Cc: linux-arm-msm, linux-remoteproc, linux-kernel, linux-arm-kernel

The rpmsg device representing struct is called rpmsg_channel and the
variable name used throughout is rpdev, with the communication happening
on endpoints it's clearer to just call this a "device" in a public API.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---

Changes since v1:
- None

 drivers/rpmsg/virtio_rpmsg_bus.c    | 42 ++++++++++++++++++-------------------
 include/linux/rpmsg.h               | 32 +++++++++++++++-------------
 samples/rpmsg/rpmsg_client_sample.c |  6 +++---
 3 files changed, 41 insertions(+), 39 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 7c7c6a8b21d9..1ac9fd871760 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -73,7 +73,7 @@ struct virtproc_info {
 	struct rpmsg_endpoint *ns_ept;
 };
 
-#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)
 
 /*
@@ -113,7 +113,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);		\
 }
@@ -127,7 +127,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);
 }
@@ -142,7 +142,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;
@@ -151,7 +151,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;
@@ -166,7 +166,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);
@@ -194,7 +194,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)
 {
@@ -282,7 +282,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,
 					struct rpmsg_channel_info chinfo)
 {
@@ -339,7 +339,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_channel_info chinfo = {};
@@ -387,7 +387,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;
@@ -451,7 +451,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);
 }
@@ -461,10 +461,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;
@@ -484,15 +484,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);
@@ -544,7 +544,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;
 
@@ -669,7 +669,7 @@ 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,
+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;
@@ -879,11 +879,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 f278407fcf48..35a0f39fd09b 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -110,7 +110,7 @@ struct rpmsg_channel_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)
@@ -119,7 +119,7 @@ struct rpmsg_channel_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;
@@ -129,7 +129,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
@@ -155,7 +155,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;
@@ -174,19 +174,21 @@ 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,
 					struct rpmsg_channel_info chinfo);
 int
-rpmsg_send_offchannel_raw(struct rpmsg_channel *, u32, u32, void *, int, bool);
+rpmsg_send_offchannel_raw(struct rpmsg_device *, u32, u32, void *, int, bool);
 
 /* use a macro to avoid include chaining to get THIS_MODULE */
 #define register_rpmsg_driver(drv) \
@@ -224,7 +226,7 @@ rpmsg_send_offchannel_raw(struct rpmsg_channel *, u32, u32, void *, int, bool);
  */
 static inline 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);
@@ -251,7 +253,7 @@ static inline int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
 static inline
 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);
@@ -281,7 +283,7 @@ static inline
 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);
 }
@@ -306,7 +308,7 @@ int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
 static inline
 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);
@@ -332,7 +334,7 @@ int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
 static inline
 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);
@@ -361,7 +363,7 @@ static inline
 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);
 }
diff --git a/samples/rpmsg/rpmsg_client_sample.c b/samples/rpmsg/rpmsg_client_sample.c
index 37975eddd64e..4fcd7ee13fb9 100644
--- a/samples/rpmsg/rpmsg_client_sample.c
+++ b/samples/rpmsg/rpmsg_client_sample.c
@@ -28,7 +28,7 @@ struct instance_data {
 	int rx_count;
 };
 
-static void rpmsg_sample_cb(struct rpmsg_channel *rpdev, void *data, int len,
+static void rpmsg_sample_cb(struct rpmsg_device *rpdev, void *data, int len,
 						void *priv, u32 src)
 {
 	int ret;
@@ -52,7 +52,7 @@ static void rpmsg_sample_cb(struct rpmsg_channel *rpdev, void *data, int len,
 		dev_err(&rpdev->dev, "rpmsg_send failed: %d\n", ret);
 }
 
-static int rpmsg_sample_probe(struct rpmsg_channel *rpdev)
+static int rpmsg_sample_probe(struct rpmsg_device *rpdev)
 {
 	int ret;
 	struct instance_data *idata;
@@ -76,7 +76,7 @@ static int rpmsg_sample_probe(struct rpmsg_channel *rpdev)
 	return 0;
 }
 
-static void rpmsg_sample_remove(struct rpmsg_channel *rpdev)
+static void rpmsg_sample_remove(struct rpmsg_device *rpdev)
 {
 	dev_info(&rpdev->dev, "rpmsg sample client driver is removed\n");
 }
-- 
2.5.0

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

* [PATCH v2 05/17] rpmsg: Clean up rpmsg device vs channel naming
@ 2016-09-01 22:27   ` Bjorn Andersson
  0 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:27 UTC (permalink / raw)
  To: linux-arm-kernel

The rpmsg device representing struct is called rpmsg_channel and the
variable name used throughout is rpdev, with the communication happening
on endpoints it's clearer to just call this a "device" in a public API.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---

Changes since v1:
- None

 drivers/rpmsg/virtio_rpmsg_bus.c    | 42 ++++++++++++++++++-------------------
 include/linux/rpmsg.h               | 32 +++++++++++++++-------------
 samples/rpmsg/rpmsg_client_sample.c |  6 +++---
 3 files changed, 41 insertions(+), 39 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 7c7c6a8b21d9..1ac9fd871760 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -73,7 +73,7 @@ struct virtproc_info {
 	struct rpmsg_endpoint *ns_ept;
 };
 
-#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)
 
 /*
@@ -113,7 +113,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);		\
 }
@@ -127,7 +127,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);
 }
@@ -142,7 +142,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;
@@ -151,7 +151,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;
@@ -166,7 +166,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);
@@ -194,7 +194,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)
 {
@@ -282,7 +282,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,
 					struct rpmsg_channel_info chinfo)
 {
@@ -339,7 +339,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_channel_info chinfo = {};
@@ -387,7 +387,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;
@@ -451,7 +451,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);
 }
@@ -461,10 +461,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;
@@ -484,15 +484,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);
@@ -544,7 +544,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;
 
@@ -669,7 +669,7 @@ 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,
+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;
@@ -879,11 +879,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 f278407fcf48..35a0f39fd09b 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -110,7 +110,7 @@ struct rpmsg_channel_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)
@@ -119,7 +119,7 @@ struct rpmsg_channel_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;
@@ -129,7 +129,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
@@ -155,7 +155,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;
@@ -174,19 +174,21 @@ 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,
 					struct rpmsg_channel_info chinfo);
 int
-rpmsg_send_offchannel_raw(struct rpmsg_channel *, u32, u32, void *, int, bool);
+rpmsg_send_offchannel_raw(struct rpmsg_device *, u32, u32, void *, int, bool);
 
 /* use a macro to avoid include chaining to get THIS_MODULE */
 #define register_rpmsg_driver(drv) \
@@ -224,7 +226,7 @@ rpmsg_send_offchannel_raw(struct rpmsg_channel *, u32, u32, void *, int, bool);
  */
 static inline 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);
@@ -251,7 +253,7 @@ static inline int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
 static inline
 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);
@@ -281,7 +283,7 @@ static inline
 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);
 }
@@ -306,7 +308,7 @@ int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
 static inline
 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);
@@ -332,7 +334,7 @@ int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
 static inline
 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);
@@ -361,7 +363,7 @@ static inline
 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);
 }
diff --git a/samples/rpmsg/rpmsg_client_sample.c b/samples/rpmsg/rpmsg_client_sample.c
index 37975eddd64e..4fcd7ee13fb9 100644
--- a/samples/rpmsg/rpmsg_client_sample.c
+++ b/samples/rpmsg/rpmsg_client_sample.c
@@ -28,7 +28,7 @@ struct instance_data {
 	int rx_count;
 };
 
-static void rpmsg_sample_cb(struct rpmsg_channel *rpdev, void *data, int len,
+static void rpmsg_sample_cb(struct rpmsg_device *rpdev, void *data, int len,
 						void *priv, u32 src)
 {
 	int ret;
@@ -52,7 +52,7 @@ static void rpmsg_sample_cb(struct rpmsg_channel *rpdev, void *data, int len,
 		dev_err(&rpdev->dev, "rpmsg_send failed: %d\n", ret);
 }
 
-static int rpmsg_sample_probe(struct rpmsg_channel *rpdev)
+static int rpmsg_sample_probe(struct rpmsg_device *rpdev)
 {
 	int ret;
 	struct instance_data *idata;
@@ -76,7 +76,7 @@ static int rpmsg_sample_probe(struct rpmsg_channel *rpdev)
 	return 0;
 }
 
-static void rpmsg_sample_remove(struct rpmsg_channel *rpdev)
+static void rpmsg_sample_remove(struct rpmsg_device *rpdev)
 {
 	dev_info(&rpdev->dev, "rpmsg sample client driver is removed\n");
 }
-- 
2.5.0

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

* [PATCH v2 06/17] rpmsg: Introduce indirection table for rpmsg_device operations
  2016-09-01 22:27 ` Bjorn Andersson
@ 2016-09-01 22:27   ` Bjorn Andersson
  -1 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:27 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson
  Cc: linux-remoteproc, linux-arm-msm, linux-arm-kernel, linux-kernel

To allow for multiple backend implementations add an indireection table
for rpmsg_device related operations and move the virtio implementation
behind this table.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---

Per Loic's comment I did consider adding parameter validation to the exposed
functions in this patch, but as the previous implementation did not gracefully
handle bad input parameters I decided to defer this until after this series has
been merged.

Changes since v1:
- Split table in device vs endpoint
- Moved ops pointer to the public structs to reduce code clutter
- Kerneldoc for rpmsg_device_ops

 drivers/rpmsg/virtio_rpmsg_bus.c | 48 +++++++++++++++++++++++++++++++++++-----
 include/linux/rpmsg.h            | 23 +++++++++++++++++++
 2 files changed, 65 insertions(+), 6 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 1ac9fd871760..088203ed1df8 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -286,10 +286,18 @@ struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev,
 					rpmsg_rx_cb_t cb, void *priv,
 					struct rpmsg_channel_info chinfo)
 {
-	return __rpmsg_create_ept(rpdev->vrp, rpdev, cb, priv, chinfo.src);
+	return rpdev->ops->create_ept(rpdev, cb, priv, chinfo);
 }
 EXPORT_SYMBOL(rpmsg_create_ept);
 
+static struct rpmsg_endpoint *virtio_rpmsg_create_ept(struct rpmsg_device *rpdev,
+						      rpmsg_rx_cb_t cb,
+						      void *priv,
+						      struct rpmsg_channel_info chinfo)
+{
+	return __rpmsg_create_ept(rpdev->vrp, rpdev, cb, priv, chinfo.src);
+}
+
 /**
  * __rpmsg_destroy_ept() - destroy an existing rpmsg endpoint
  * @vrp: virtproc which owns this ept
@@ -341,7 +349,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_channel_info chinfo = {};
 	struct rpmsg_endpoint *ept;
 	int err;
@@ -367,6 +374,18 @@ static int rpmsg_dev_probe(struct device *dev)
 		goto out;
 	}
 
+	if (rpdev->ops->announce_create)
+		err = rpdev->ops->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)) {
@@ -381,15 +400,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 */
@@ -406,6 +423,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->ops->announce_destroy)
+		err = rpdev->ops->announce_destroy(rpdev);
+
 	rpdrv->remove(rpdev);
 
 	rpmsg_destroy_ept(rpdev->ept);
@@ -479,6 +508,12 @@ static int rpmsg_device_match(struct device *dev, void *data)
 	return 1;
 }
 
+static const struct rpmsg_device_ops virtio_rpmsg_ops = {
+	.create_ept = virtio_rpmsg_create_ept,
+	.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
@@ -508,6 +543,7 @@ static struct rpmsg_device *rpmsg_create_channel(struct virtproc_info *vrp,
 	rpdev->vrp = vrp;
 	rpdev->src = chinfo->src;
 	rpdev->dst = chinfo->dst;
+	rpdev->ops = &virtio_rpmsg_ops;
 
 	/*
 	 * rpmsg server channels has predefined local address (for now),
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index 35a0f39fd09b..9fdcfc7c7837 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -96,6 +96,8 @@ enum rpmsg_ns_flags {
 #define RPMSG_ADDR_ANY		0xFFFFFFFF
 
 struct virtproc_info;
+struct rpmsg_endpoint;
+struct rpmsg_device_ops;
 
 /**
  * struct rpmsg_channel_info - channel info representation
@@ -127,11 +129,32 @@ struct rpmsg_device {
 	u32 dst;
 	struct rpmsg_endpoint *ept;
 	bool announce;
+
+	const struct rpmsg_device_ops *ops;
 };
 
 typedef void (*rpmsg_rx_cb_t)(struct rpmsg_device *, void *, int, void *, u32);
 
 /**
+ * struct rpmsg_device_ops - indirection table for the rpmsg_device operations
+ * @create_ept:		create backend-specific endpoint, requried
+ * @announce_create:	announce presence of new channel, optional
+ * @announce_destroy:	announce destruction of channel, optional
+ *
+ * Indirection table for the operations that a rpmsg backend should implement.
+ * @announce_create and @announce_destroy are optional as the backend might
+ * advertise new channels implicitly by creating the endpoints.
+ */
+struct rpmsg_device_ops {
+	struct rpmsg_endpoint *(*create_ept)(struct rpmsg_device *rpdev,
+					    rpmsg_rx_cb_t cb, void *priv,
+					    struct rpmsg_channel_info chinfo);
+
+	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
  * @rpdev: rpmsg channel device
  * @refcount: when this drops to zero, the ept is deallocated
-- 
2.5.0

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

* [PATCH v2 06/17] rpmsg: Introduce indirection table for rpmsg_device operations
@ 2016-09-01 22:27   ` Bjorn Andersson
  0 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:27 UTC (permalink / raw)
  To: linux-arm-kernel

To allow for multiple backend implementations add an indireection table
for rpmsg_device related operations and move the virtio implementation
behind this table.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---

Per Loic's comment I did consider adding parameter validation to the exposed
functions in this patch, but as the previous implementation did not gracefully
handle bad input parameters I decided to defer this until after this series has
been merged.

Changes since v1:
- Split table in device vs endpoint
- Moved ops pointer to the public structs to reduce code clutter
- Kerneldoc for rpmsg_device_ops

 drivers/rpmsg/virtio_rpmsg_bus.c | 48 +++++++++++++++++++++++++++++++++++-----
 include/linux/rpmsg.h            | 23 +++++++++++++++++++
 2 files changed, 65 insertions(+), 6 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 1ac9fd871760..088203ed1df8 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -286,10 +286,18 @@ struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev,
 					rpmsg_rx_cb_t cb, void *priv,
 					struct rpmsg_channel_info chinfo)
 {
-	return __rpmsg_create_ept(rpdev->vrp, rpdev, cb, priv, chinfo.src);
+	return rpdev->ops->create_ept(rpdev, cb, priv, chinfo);
 }
 EXPORT_SYMBOL(rpmsg_create_ept);
 
+static struct rpmsg_endpoint *virtio_rpmsg_create_ept(struct rpmsg_device *rpdev,
+						      rpmsg_rx_cb_t cb,
+						      void *priv,
+						      struct rpmsg_channel_info chinfo)
+{
+	return __rpmsg_create_ept(rpdev->vrp, rpdev, cb, priv, chinfo.src);
+}
+
 /**
  * __rpmsg_destroy_ept() - destroy an existing rpmsg endpoint
  * @vrp: virtproc which owns this ept
@@ -341,7 +349,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_channel_info chinfo = {};
 	struct rpmsg_endpoint *ept;
 	int err;
@@ -367,6 +374,18 @@ static int rpmsg_dev_probe(struct device *dev)
 		goto out;
 	}
 
+	if (rpdev->ops->announce_create)
+		err = rpdev->ops->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)) {
@@ -381,15 +400,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 */
@@ -406,6 +423,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->ops->announce_destroy)
+		err = rpdev->ops->announce_destroy(rpdev);
+
 	rpdrv->remove(rpdev);
 
 	rpmsg_destroy_ept(rpdev->ept);
@@ -479,6 +508,12 @@ static int rpmsg_device_match(struct device *dev, void *data)
 	return 1;
 }
 
+static const struct rpmsg_device_ops virtio_rpmsg_ops = {
+	.create_ept = virtio_rpmsg_create_ept,
+	.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
@@ -508,6 +543,7 @@ static struct rpmsg_device *rpmsg_create_channel(struct virtproc_info *vrp,
 	rpdev->vrp = vrp;
 	rpdev->src = chinfo->src;
 	rpdev->dst = chinfo->dst;
+	rpdev->ops = &virtio_rpmsg_ops;
 
 	/*
 	 * rpmsg server channels has predefined local address (for now),
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index 35a0f39fd09b..9fdcfc7c7837 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -96,6 +96,8 @@ enum rpmsg_ns_flags {
 #define RPMSG_ADDR_ANY		0xFFFFFFFF
 
 struct virtproc_info;
+struct rpmsg_endpoint;
+struct rpmsg_device_ops;
 
 /**
  * struct rpmsg_channel_info - channel info representation
@@ -127,11 +129,32 @@ struct rpmsg_device {
 	u32 dst;
 	struct rpmsg_endpoint *ept;
 	bool announce;
+
+	const struct rpmsg_device_ops *ops;
 };
 
 typedef void (*rpmsg_rx_cb_t)(struct rpmsg_device *, void *, int, void *, u32);
 
 /**
+ * struct rpmsg_device_ops - indirection table for the rpmsg_device operations
+ * @create_ept:		create backend-specific endpoint, requried
+ * @announce_create:	announce presence of new channel, optional
+ * @announce_destroy:	announce destruction of channel, optional
+ *
+ * Indirection table for the operations that a rpmsg backend should implement.
+ * @announce_create and @announce_destroy are optional as the backend might
+ * advertise new channels implicitly by creating the endpoints.
+ */
+struct rpmsg_device_ops {
+	struct rpmsg_endpoint *(*create_ept)(struct rpmsg_device *rpdev,
+					    rpmsg_rx_cb_t cb, void *priv,
+					    struct rpmsg_channel_info chinfo);
+
+	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
  * @rpdev: rpmsg channel device
  * @refcount: when this drops to zero, the ept is deallocated
-- 
2.5.0

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

* [PATCH v2 07/17] rpmsg: Move rpmsg_device API to new file
  2016-09-01 22:27 ` Bjorn Andersson
@ 2016-09-01 22:27   ` Bjorn Andersson
  -1 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:27 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson
  Cc: linux-remoteproc, linux-arm-msm, linux-arm-kernel, linux-kernel

Extract the now indirect rpmsg_create_ept() interface to a separate
file and start building up a rpmsg core.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---

Changes since v1:
- Extracted the big move into several smaller patches

 drivers/remoteproc/Kconfig       |  4 +--
 drivers/rpmsg/Kconfig            |  4 +++
 drivers/rpmsg/Makefile           |  3 +-
 drivers/rpmsg/rpmsg_core.c       | 71 ++++++++++++++++++++++++++++++++++++++++
 drivers/rpmsg/virtio_rpmsg_bus.c | 48 ---------------------------
 5 files changed, 79 insertions(+), 51 deletions(-)
 create mode 100644 drivers/rpmsg/rpmsg_core.c

diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index 1a8bf76a925f..70ec8130622d 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -17,7 +17,7 @@ config OMAP_REMOTEPROC
 	select REMOTEPROC
 	select MAILBOX
 	select OMAP2PLUS_MBOX
-	select RPMSG
+	select RPMSG_VIRTIO
 	help
 	  Say y here to support OMAP's remote processors (dual M3
 	  and DSP on OMAP4) via the remote processor framework.
@@ -59,7 +59,7 @@ config DA8XX_REMOTEPROC
 	depends on ARCH_DAVINCI_DA8XX
 	select CMA if MMU
 	select REMOTEPROC
-	select RPMSG
+	select RPMSG_VIRTIO
 	help
 	  Say y here to support DA8xx/OMAP-L13x remote processors via the
 	  remote processor framework.
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..c48ea55ad380 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..c511b5d64f89
--- /dev/null
+++ b/drivers/rpmsg/rpmsg_core.c
@@ -0,0 +1,71 @@
+/*
+ * 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/rpmsg.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
+ * @chinfo: channel_info with the 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,
+					struct rpmsg_channel_info chinfo)
+{
+	return rpdev->ops->create_ept(rpdev, cb, priv, chinfo);
+}
+EXPORT_SYMBOL(rpmsg_create_ept);
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 088203ed1df8..605e09c96d65 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -242,54 +242,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
- * @chinfo: channel_info with the 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,
-					struct rpmsg_channel_info chinfo)
-{
-	return rpdev->ops->create_ept(rpdev, cb, priv, chinfo);
-}
-EXPORT_SYMBOL(rpmsg_create_ept);
-
 static struct rpmsg_endpoint *virtio_rpmsg_create_ept(struct rpmsg_device *rpdev,
 						      rpmsg_rx_cb_t cb,
 						      void *priv,
-- 
2.5.0

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

* [PATCH v2 07/17] rpmsg: Move rpmsg_device API to new file
@ 2016-09-01 22:27   ` Bjorn Andersson
  0 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:27 UTC (permalink / raw)
  To: linux-arm-kernel

Extract the now indirect rpmsg_create_ept() interface to a separate
file and start building up a rpmsg core.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---

Changes since v1:
- Extracted the big move into several smaller patches

 drivers/remoteproc/Kconfig       |  4 +--
 drivers/rpmsg/Kconfig            |  4 +++
 drivers/rpmsg/Makefile           |  3 +-
 drivers/rpmsg/rpmsg_core.c       | 71 ++++++++++++++++++++++++++++++++++++++++
 drivers/rpmsg/virtio_rpmsg_bus.c | 48 ---------------------------
 5 files changed, 79 insertions(+), 51 deletions(-)
 create mode 100644 drivers/rpmsg/rpmsg_core.c

diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index 1a8bf76a925f..70ec8130622d 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -17,7 +17,7 @@ config OMAP_REMOTEPROC
 	select REMOTEPROC
 	select MAILBOX
 	select OMAP2PLUS_MBOX
-	select RPMSG
+	select RPMSG_VIRTIO
 	help
 	  Say y here to support OMAP's remote processors (dual M3
 	  and DSP on OMAP4) via the remote processor framework.
@@ -59,7 +59,7 @@ config DA8XX_REMOTEPROC
 	depends on ARCH_DAVINCI_DA8XX
 	select CMA if MMU
 	select REMOTEPROC
-	select RPMSG
+	select RPMSG_VIRTIO
 	help
 	  Say y here to support DA8xx/OMAP-L13x remote processors via the
 	  remote processor framework.
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..c48ea55ad380 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..c511b5d64f89
--- /dev/null
+++ b/drivers/rpmsg/rpmsg_core.c
@@ -0,0 +1,71 @@
+/*
+ * 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/rpmsg.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
+ * @chinfo: channel_info with the 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,
+					struct rpmsg_channel_info chinfo)
+{
+	return rpdev->ops->create_ept(rpdev, cb, priv, chinfo);
+}
+EXPORT_SYMBOL(rpmsg_create_ept);
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 088203ed1df8..605e09c96d65 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -242,54 +242,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
- * @chinfo: channel_info with the 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,
-					struct rpmsg_channel_info chinfo)
-{
-	return rpdev->ops->create_ept(rpdev, cb, priv, chinfo);
-}
-EXPORT_SYMBOL(rpmsg_create_ept);
-
 static struct rpmsg_endpoint *virtio_rpmsg_create_ept(struct rpmsg_device *rpdev,
 						      rpmsg_rx_cb_t cb,
 						      void *priv,
-- 
2.5.0

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

* [PATCH v2 08/17] rpmsg: Indirection table for rpmsg_endpoint operations
  2016-09-01 22:27 ` Bjorn Andersson
@ 2016-09-01 22:28   ` Bjorn Andersson
  -1 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:28 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson
  Cc: linux-remoteproc, linux-arm-msm, linux-arm-kernel, linux-kernel

Add indirection table for rpmsg_endpoint related operations and move
virtio implementation behind this, this finishes of the decoupling of
the virtio implementation from the public API.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---

Per Loic's comment I did consider adding parameter validation to the exposed
functions in this patch, but as the previous implementation did not gracefully
handle bad input parameters I decided to defer this until after this series has
been merged.

Changes since v1:
- Split indirection table into device and endpoint ops
- Moved ops pointer to the public structs to reduce code clutter
- Kerneldoc for rpmsg_endpoint_ops

 drivers/rpmsg/virtio_rpmsg_bus.c | 85 ++++++++++++++++++++++++++++++++++++++--
 include/linux/rpmsg.h            | 62 +++++++++++++++++------------
 2 files changed, 120 insertions(+), 27 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 605e09c96d65..e5f256791fd3 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -107,6 +107,18 @@ struct virtproc_info {
 /* Address 53 is reserved for advertising remote services */
 #define RPMSG_NS_ADDR			(53)
 
+static void virtio_rpmsg_destroy_ept(struct rpmsg_endpoint *ept);
+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								\
@@ -172,6 +184,16 @@ static int rpmsg_uevent(struct device *dev, struct kobj_uevent_env *env)
 					rpdev->id.name);
 }
 
+static const struct rpmsg_endpoint_ops virtio_endpoint_ops = {
+	.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,
+};
+
 /**
  * __ept_release() - deallocate an rpmsg endpoint
  * @kref: the ept's reference count
@@ -212,6 +234,7 @@ static struct rpmsg_endpoint *__rpmsg_create_ept(struct virtproc_info *vrp,
 	ept->rpdev = rpdev;
 	ept->cb = cb;
 	ept->priv = priv;
+	ept->ops = &virtio_endpoint_ops;
 
 	/* do we need to allocate a local address ? */
 	if (addr == RPMSG_ADDR_ANY) {
@@ -285,10 +308,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->ops->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
@@ -657,8 +685,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_device *rpdev, u32 src, u32 dst,
-			      void *data, int len, bool wait)
+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 device *dev = &rpdev->dev;
@@ -754,6 +783,56 @@ out:
 }
 EXPORT_SYMBOL(rpmsg_send_offchannel_raw);
 
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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 9fdcfc7c7837..d54458effd54 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -96,8 +96,10 @@ enum rpmsg_ns_flags {
 #define RPMSG_ADDR_ANY		0xFFFFFFFF
 
 struct virtproc_info;
+struct rpmsg_device;
 struct rpmsg_endpoint;
 struct rpmsg_device_ops;
+struct rpmsg_endpoint_ops;
 
 /**
  * struct rpmsg_channel_info - channel info representation
@@ -184,6 +186,36 @@ struct rpmsg_endpoint {
 	struct mutex cb_lock;
 	u32 addr;
 	void *priv;
+
+	const struct rpmsg_endpoint_ops *ops;
+};
+
+/**
+ * struct rpmsg_endpoint_ops - indirection table for rpmsg_endpoint operations
+ * @destroy_ept:	destroy the given endpoint, required
+ * @send:		see @rpmsg_send(), required
+ * @sendto:		see @rpmsg_sendto(), optional
+ * @send_offchannel:	see @rpmsg_send_offchannel(), optional
+ * @trysend:		see @rpmsg_trysend(), required
+ * @trysendto:		see @rpmsg_trysendto(), optional
+ * @trysend_offchannel:	see @rpmsg_trysend_offchannel(), optional
+ *
+ * Indirection table for the operations that a rpmsg backend should implement.
+ * In addition to @destroy_ept, the backend must at least implement @send and
+ * @trysend, while the variants sending data off-channel are optional.
+ */
+struct rpmsg_endpoint_ops {
+	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);
 };
 
 /**
@@ -210,8 +242,6 @@ void rpmsg_destroy_ept(struct rpmsg_endpoint *);
 struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *,
 					rpmsg_rx_cb_t cb, void *priv,
 					struct rpmsg_channel_info chinfo);
-int
-rpmsg_send_offchannel_raw(struct rpmsg_device *, u32, u32, void *, int, bool);
 
 /* use a macro to avoid include chaining to get THIS_MODULE */
 #define register_rpmsg_driver(drv) \
@@ -249,10 +279,7 @@ rpmsg_send_offchannel_raw(struct rpmsg_device *, u32, u32, void *, int, bool);
  */
 static inline int 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);
+	return ept->ops->send(ept, data, len);
 }
 
 /**
@@ -276,10 +303,7 @@ static inline int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
 static inline
 int 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);
+	return ept->ops->sendto(ept, data, len, dst);
 }
 
 /**
@@ -306,9 +330,7 @@ static inline
 int 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);
+	return ept->ops->send_offchannel(ept, src, dst, data, len);
 }
 
 /**
@@ -331,10 +353,7 @@ int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
 static inline
 int 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);
+	return ept->ops->trysend(ept, data, len);
 }
 
 /**
@@ -357,10 +376,7 @@ int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
 static inline
 int 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);
+	return ept->ops->trysendto(ept, data, len, dst);
 }
 
 /**
@@ -386,9 +402,7 @@ static inline
 int 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);
+	return ept->ops->trysend_offchannel(ept, src, dst, data, len);
 }
 
 #endif /* _LINUX_RPMSG_H */
-- 
2.5.0

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

* [PATCH v2 08/17] rpmsg: Indirection table for rpmsg_endpoint operations
@ 2016-09-01 22:28   ` Bjorn Andersson
  0 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:28 UTC (permalink / raw)
  To: linux-arm-kernel

Add indirection table for rpmsg_endpoint related operations and move
virtio implementation behind this, this finishes of the decoupling of
the virtio implementation from the public API.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---

Per Loic's comment I did consider adding parameter validation to the exposed
functions in this patch, but as the previous implementation did not gracefully
handle bad input parameters I decided to defer this until after this series has
been merged.

Changes since v1:
- Split indirection table into device and endpoint ops
- Moved ops pointer to the public structs to reduce code clutter
- Kerneldoc for rpmsg_endpoint_ops

 drivers/rpmsg/virtio_rpmsg_bus.c | 85 ++++++++++++++++++++++++++++++++++++++--
 include/linux/rpmsg.h            | 62 +++++++++++++++++------------
 2 files changed, 120 insertions(+), 27 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 605e09c96d65..e5f256791fd3 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -107,6 +107,18 @@ struct virtproc_info {
 /* Address 53 is reserved for advertising remote services */
 #define RPMSG_NS_ADDR			(53)
 
+static void virtio_rpmsg_destroy_ept(struct rpmsg_endpoint *ept);
+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								\
@@ -172,6 +184,16 @@ static int rpmsg_uevent(struct device *dev, struct kobj_uevent_env *env)
 					rpdev->id.name);
 }
 
+static const struct rpmsg_endpoint_ops virtio_endpoint_ops = {
+	.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,
+};
+
 /**
  * __ept_release() - deallocate an rpmsg endpoint
  * @kref: the ept's reference count
@@ -212,6 +234,7 @@ static struct rpmsg_endpoint *__rpmsg_create_ept(struct virtproc_info *vrp,
 	ept->rpdev = rpdev;
 	ept->cb = cb;
 	ept->priv = priv;
+	ept->ops = &virtio_endpoint_ops;
 
 	/* do we need to allocate a local address ? */
 	if (addr == RPMSG_ADDR_ANY) {
@@ -285,10 +308,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->ops->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
@@ -657,8 +685,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_device *rpdev, u32 src, u32 dst,
-			      void *data, int len, bool wait)
+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 device *dev = &rpdev->dev;
@@ -754,6 +783,56 @@ out:
 }
 EXPORT_SYMBOL(rpmsg_send_offchannel_raw);
 
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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 9fdcfc7c7837..d54458effd54 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -96,8 +96,10 @@ enum rpmsg_ns_flags {
 #define RPMSG_ADDR_ANY		0xFFFFFFFF
 
 struct virtproc_info;
+struct rpmsg_device;
 struct rpmsg_endpoint;
 struct rpmsg_device_ops;
+struct rpmsg_endpoint_ops;
 
 /**
  * struct rpmsg_channel_info - channel info representation
@@ -184,6 +186,36 @@ struct rpmsg_endpoint {
 	struct mutex cb_lock;
 	u32 addr;
 	void *priv;
+
+	const struct rpmsg_endpoint_ops *ops;
+};
+
+/**
+ * struct rpmsg_endpoint_ops - indirection table for rpmsg_endpoint operations
+ * @destroy_ept:	destroy the given endpoint, required
+ * @send:		see @rpmsg_send(), required
+ * @sendto:		see @rpmsg_sendto(), optional
+ * @send_offchannel:	see @rpmsg_send_offchannel(), optional
+ * @trysend:		see @rpmsg_trysend(), required
+ * @trysendto:		see @rpmsg_trysendto(), optional
+ * @trysend_offchannel:	see @rpmsg_trysend_offchannel(), optional
+ *
+ * Indirection table for the operations that a rpmsg backend should implement.
+ * In addition to @destroy_ept, the backend must at least implement @send and
+ * @trysend, while the variants sending data off-channel are optional.
+ */
+struct rpmsg_endpoint_ops {
+	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);
 };
 
 /**
@@ -210,8 +242,6 @@ void rpmsg_destroy_ept(struct rpmsg_endpoint *);
 struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *,
 					rpmsg_rx_cb_t cb, void *priv,
 					struct rpmsg_channel_info chinfo);
-int
-rpmsg_send_offchannel_raw(struct rpmsg_device *, u32, u32, void *, int, bool);
 
 /* use a macro to avoid include chaining to get THIS_MODULE */
 #define register_rpmsg_driver(drv) \
@@ -249,10 +279,7 @@ rpmsg_send_offchannel_raw(struct rpmsg_device *, u32, u32, void *, int, bool);
  */
 static inline int 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);
+	return ept->ops->send(ept, data, len);
 }
 
 /**
@@ -276,10 +303,7 @@ static inline int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
 static inline
 int 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);
+	return ept->ops->sendto(ept, data, len, dst);
 }
 
 /**
@@ -306,9 +330,7 @@ static inline
 int 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);
+	return ept->ops->send_offchannel(ept, src, dst, data, len);
 }
 
 /**
@@ -331,10 +353,7 @@ int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
 static inline
 int 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);
+	return ept->ops->trysend(ept, data, len);
 }
 
 /**
@@ -357,10 +376,7 @@ int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
 static inline
 int 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);
+	return ept->ops->trysendto(ept, data, len, dst);
 }
 
 /**
@@ -386,9 +402,7 @@ static inline
 int 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);
+	return ept->ops->trysend_offchannel(ept, src, dst, data, len);
 }
 
 #endif /* _LINUX_RPMSG_H */
-- 
2.5.0

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

* [PATCH v2 09/17] rpmsg: Move endpoint related interface to rpmsg core
  2016-09-01 22:27 ` Bjorn Andersson
@ 2016-09-01 22:28   ` Bjorn Andersson
  -1 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:28 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson
  Cc: linux-remoteproc, linux-arm-msm, linux-arm-kernel, linux-kernel

Move the rpmsg_send() and rpmsg_destroy_ept() interface to the rpmsg
core, so that we eventually can hide the rpmsg_endpoint ops from the
public API.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---

Changes since v1:
- None

 drivers/rpmsg/rpmsg_core.c       | 160 +++++++++++++++++++++++++++++++++++++++
 drivers/rpmsg/virtio_rpmsg_bus.c |  13 ----
 include/linux/rpmsg.h            | 148 ++----------------------------------
 3 files changed, 166 insertions(+), 155 deletions(-)

diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
index c511b5d64f89..3bee8e03a387 100644
--- a/drivers/rpmsg/rpmsg_core.c
+++ b/drivers/rpmsg/rpmsg_core.c
@@ -69,3 +69,163 @@ struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev,
 	return rpdev->ops->create_ept(rpdev, cb, priv, chinfo);
 }
 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->ops->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)
+{
+	return ept->ops->send(ept, data, len);
+}
+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)
+{
+	return ept->ops->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)
+{
+	return ept->ops->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)
+{
+	return ept->ops->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)
+{
+	return ept->ops->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)
+{
+	return ept->ops->trysend_offchannel(ept, src, dst, data, len);
+}
+EXPORT_SYMBOL(rpmsg_trysend_offchannel);
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index e5f256791fd3..184663276e51 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -299,19 +299,6 @@ __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->ops->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);
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index d54458effd54..99efd598590e 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -259,150 +259,14 @@ struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *,
 	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)
-{
-	return ept->ops->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.
- */
-static inline
-int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
-{
-	return ept->ops->sendto(ept, data, len, dst);
-}
-
-/**
- * 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)
-{
-	return ept->ops->send_offchannel(ept, src, dst, data, len);
-}
+			  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 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.
- */
-static inline
-int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
-{
-	return ept->ops->trysend(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 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)
-{
-	return ept->ops->trysendto(ept, data, len, dst);
-}
-
-/**
- * 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)
-{
-	return ept->ops->trysend_offchannel(ept, src, dst, data, len);
-}
+			     void *data, int len);
 
 #endif /* _LINUX_RPMSG_H */
-- 
2.5.0

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

* [PATCH v2 09/17] rpmsg: Move endpoint related interface to rpmsg core
@ 2016-09-01 22:28   ` Bjorn Andersson
  0 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:28 UTC (permalink / raw)
  To: linux-arm-kernel

Move the rpmsg_send() and rpmsg_destroy_ept() interface to the rpmsg
core, so that we eventually can hide the rpmsg_endpoint ops from the
public API.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---

Changes since v1:
- None

 drivers/rpmsg/rpmsg_core.c       | 160 +++++++++++++++++++++++++++++++++++++++
 drivers/rpmsg/virtio_rpmsg_bus.c |  13 ----
 include/linux/rpmsg.h            | 148 ++----------------------------------
 3 files changed, 166 insertions(+), 155 deletions(-)

diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
index c511b5d64f89..3bee8e03a387 100644
--- a/drivers/rpmsg/rpmsg_core.c
+++ b/drivers/rpmsg/rpmsg_core.c
@@ -69,3 +69,163 @@ struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev,
 	return rpdev->ops->create_ept(rpdev, cb, priv, chinfo);
 }
 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->ops->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)
+{
+	return ept->ops->send(ept, data, len);
+}
+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)
+{
+	return ept->ops->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)
+{
+	return ept->ops->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)
+{
+	return ept->ops->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)
+{
+	return ept->ops->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)
+{
+	return ept->ops->trysend_offchannel(ept, src, dst, data, len);
+}
+EXPORT_SYMBOL(rpmsg_trysend_offchannel);
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index e5f256791fd3..184663276e51 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -299,19 +299,6 @@ __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->ops->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);
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index d54458effd54..99efd598590e 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -259,150 +259,14 @@ struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *,
 	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)
-{
-	return ept->ops->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.
- */
-static inline
-int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
-{
-	return ept->ops->sendto(ept, data, len, dst);
-}
-
-/**
- * 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)
-{
-	return ept->ops->send_offchannel(ept, src, dst, data, len);
-}
+			  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 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.
- */
-static inline
-int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
-{
-	return ept->ops->trysend(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 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)
-{
-	return ept->ops->trysendto(ept, data, len, dst);
-}
-
-/**
- * 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)
-{
-	return ept->ops->trysend_offchannel(ept, src, dst, data, len);
-}
+			     void *data, int len);
 
 #endif /* _LINUX_RPMSG_H */
-- 
2.5.0

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

* [PATCH v2 10/17] rpmsg: Move helper for finding rpmsg devices to core
  2016-09-01 22:27 ` Bjorn Andersson
@ 2016-09-01 22:28   ` Bjorn Andersson
  -1 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:28 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson
  Cc: linux-remoteproc, linux-arm-msm, linux-arm-kernel, linux-kernel

Extract and move the helper function for finding rpmsg child devices to
the core.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---

Changes since v1:
- Extracted this from the big move to rpmsg_core.c in v1

 drivers/rpmsg/rpmsg_core.c       | 33 +++++++++++++++++++++++++++++++++
 drivers/rpmsg/rpmsg_internal.h   | 31 +++++++++++++++++++++++++++++++
 drivers/rpmsg/virtio_rpmsg_bus.c | 29 ++++-------------------------
 3 files changed, 68 insertions(+), 25 deletions(-)
 create mode 100644 drivers/rpmsg/rpmsg_internal.h

diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
index 3bee8e03a387..81101775fed0 100644
--- a/drivers/rpmsg/rpmsg_core.c
+++ b/drivers/rpmsg/rpmsg_core.c
@@ -22,6 +22,8 @@
 #include <linux/kernel.h>
 #include <linux/rpmsg.h>
 
+#include "rpmsg_internal.h"
+
 /**
  * rpmsg_create_ept() - create a new rpmsg_endpoint
  * @rpdev: rpmsg channel device
@@ -229,3 +231,34 @@ int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
 	return ept->ops->trysend_offchannel(ept, src, dst, data, len);
 }
 EXPORT_SYMBOL(rpmsg_trysend_offchannel);
+
+/*
+ * 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;
+}
+
+struct device *rpmsg_find_device(struct device *parent,
+				 struct rpmsg_channel_info *chinfo)
+{
+	return device_find_child(parent, chinfo, rpmsg_device_match);
+
+}
+EXPORT_SYMBOL(rpmsg_find_device);
diff --git a/drivers/rpmsg/rpmsg_internal.h b/drivers/rpmsg/rpmsg_internal.h
new file mode 100644
index 000000000000..205debf4ea65
--- /dev/null
+++ b/drivers/rpmsg/rpmsg_internal.h
@@ -0,0 +1,31 @@
+/*
+ * remote processor messaging bus internals
+ *
+ * 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__
+
+#include <linux/rpmsg.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 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 184663276e51..488fd93a290c 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
@@ -452,29 +454,6 @@ static void rpmsg_release_device(struct 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_ops virtio_rpmsg_ops = {
 	.create_ept = virtio_rpmsg_create_ept,
 	.announce_create = virtio_rpmsg_announce_create,
@@ -494,7 +473,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);
@@ -547,7 +526,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_device_match);
+	dev = rpmsg_find_device(&vdev->dev, chinfo);
 	if (!dev)
 		return -EINVAL;
 
-- 
2.5.0

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

* [PATCH v2 10/17] rpmsg: Move helper for finding rpmsg devices to core
@ 2016-09-01 22:28   ` Bjorn Andersson
  0 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:28 UTC (permalink / raw)
  To: linux-arm-kernel

Extract and move the helper function for finding rpmsg child devices to
the core.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---

Changes since v1:
- Extracted this from the big move to rpmsg_core.c in v1

 drivers/rpmsg/rpmsg_core.c       | 33 +++++++++++++++++++++++++++++++++
 drivers/rpmsg/rpmsg_internal.h   | 31 +++++++++++++++++++++++++++++++
 drivers/rpmsg/virtio_rpmsg_bus.c | 29 ++++-------------------------
 3 files changed, 68 insertions(+), 25 deletions(-)
 create mode 100644 drivers/rpmsg/rpmsg_internal.h

diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
index 3bee8e03a387..81101775fed0 100644
--- a/drivers/rpmsg/rpmsg_core.c
+++ b/drivers/rpmsg/rpmsg_core.c
@@ -22,6 +22,8 @@
 #include <linux/kernel.h>
 #include <linux/rpmsg.h>
 
+#include "rpmsg_internal.h"
+
 /**
  * rpmsg_create_ept() - create a new rpmsg_endpoint
  * @rpdev: rpmsg channel device
@@ -229,3 +231,34 @@ int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
 	return ept->ops->trysend_offchannel(ept, src, dst, data, len);
 }
 EXPORT_SYMBOL(rpmsg_trysend_offchannel);
+
+/*
+ * 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;
+}
+
+struct device *rpmsg_find_device(struct device *parent,
+				 struct rpmsg_channel_info *chinfo)
+{
+	return device_find_child(parent, chinfo, rpmsg_device_match);
+
+}
+EXPORT_SYMBOL(rpmsg_find_device);
diff --git a/drivers/rpmsg/rpmsg_internal.h b/drivers/rpmsg/rpmsg_internal.h
new file mode 100644
index 000000000000..205debf4ea65
--- /dev/null
+++ b/drivers/rpmsg/rpmsg_internal.h
@@ -0,0 +1,31 @@
+/*
+ * remote processor messaging bus internals
+ *
+ * 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__
+
+#include <linux/rpmsg.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 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 184663276e51..488fd93a290c 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
@@ -452,29 +454,6 @@ static void rpmsg_release_device(struct 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_ops virtio_rpmsg_ops = {
 	.create_ept = virtio_rpmsg_create_ept,
 	.announce_create = virtio_rpmsg_announce_create,
@@ -494,7 +473,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);
@@ -547,7 +526,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_device_match);
+	dev = rpmsg_find_device(&vdev->dev, chinfo);
 	if (!dev)
 		return -EINVAL;
 
-- 
2.5.0

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

* [PATCH v2 11/17] rpmsg: Split off generic tail of create_channel()
  2016-09-01 22:27 ` Bjorn Andersson
@ 2016-09-01 22:28   ` Bjorn Andersson
  -1 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:28 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>
---

Changes since v1:
- None

 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 488fd93a290c..e1052622c6a2 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -120,6 +120,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)			\
@@ -499,10 +500,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;
 
@@ -510,10 +523,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] 68+ messages in thread

* [PATCH v2 11/17] rpmsg: Split off generic tail of create_channel()
@ 2016-09-01 22:28   ` Bjorn Andersson
  0 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:28 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>
---

Changes since v1:
- None

 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 488fd93a290c..e1052622c6a2 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -120,6 +120,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)			\
@@ -499,10 +500,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;
 
@@ -510,10 +523,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] 68+ messages in thread

* [PATCH v2 12/17] rpmsg: Split rpmsg core and virtio backend
  2016-09-01 22:27 ` Bjorn Andersson
@ 2016-09-01 22:28   ` Bjorn Andersson
  -1 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:28 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>
---

Changes since v1:
- Split out part of this move to earlier patches in the series
- Adapted to the move of the ops references to the public structs

 drivers/rpmsg/rpmsg_core.c       | 231 +++++++++++++++++++++++++++++++++++++++
 drivers/rpmsg/rpmsg_internal.h   |   4 +
 drivers/rpmsg/virtio_rpmsg_bus.c | 225 +-------------------------------------
 3 files changed, 237 insertions(+), 223 deletions(-)

diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
index 81101775fed0..e1d765a7372c 100644
--- a/drivers/rpmsg/rpmsg_core.c
+++ b/drivers/rpmsg/rpmsg_core.c
@@ -262,3 +262,234 @@ struct device *rpmsg_find_device(struct device *parent,
 
 }
 EXPORT_SYMBOL(rpmsg_find_device);
+
+/* 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_channel_info chinfo = {};
+	struct rpmsg_endpoint *ept;
+	int err;
+
+	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;
+		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->ops->announce_create)
+		err = rpdev->ops->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->ops->announce_destroy)
+		err = rpdev->ops->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);
+
+/*
+ * 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
index 205debf4ea65..8ac98fd0bf1d 100644
--- a/drivers/rpmsg/rpmsg_internal.h
+++ b/drivers/rpmsg/rpmsg_internal.h
@@ -25,6 +25,10 @@
 #define to_rpmsg_device(d) container_of(d, struct rpmsg_device, dev)
 #define to_rpmsg_driver(d) container_of(d, struct rpmsg_driver, drv)
 
+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);
 
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index e1052622c6a2..31cd526f690d 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -75,9 +75,6 @@ struct virtproc_info {
 	struct rpmsg_endpoint *ns_ept;
 };
 
-#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
@@ -120,72 +117,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);
-}
 
 static const struct rpmsg_endpoint_ops virtio_endpoint_ops = {
 	.destroy_ept = virtio_rpmsg_destroy_ept,
@@ -307,49 +238,6 @@ 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_channel_info chinfo = {};
-	struct rpmsg_endpoint *ept;
-	int err;
-
-	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;
-		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->ops->announce_create)
-		err = rpdev->ops->announce_create(rpdev);
-out:
-	return err;
-}
-
 static int virtio_rpmsg_announce_create(struct rpmsg_device *rpdev)
 {
 	struct virtproc_info *vrp = rpdev->vrp;
@@ -396,65 +284,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->ops->announce_destroy)
-		err = rpdev->ops->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);
-}
-
 static const struct rpmsg_device_ops virtio_rpmsg_ops = {
 	.create_ept = virtio_rpmsg_create_ept,
 	.announce_create = virtio_rpmsg_announce_create,
@@ -508,47 +337,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 = rpmsg_find_device(&vdev->dev, chinfo);
-	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)
 {
@@ -967,7 +755,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 {
@@ -1152,17 +940,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;
 }
@@ -1171,7 +951,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] 68+ messages in thread

* [PATCH v2 12/17] rpmsg: Split rpmsg core and virtio backend
@ 2016-09-01 22:28   ` Bjorn Andersson
  0 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:28 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>
---

Changes since v1:
- Split out part of this move to earlier patches in the series
- Adapted to the move of the ops references to the public structs

 drivers/rpmsg/rpmsg_core.c       | 231 +++++++++++++++++++++++++++++++++++++++
 drivers/rpmsg/rpmsg_internal.h   |   4 +
 drivers/rpmsg/virtio_rpmsg_bus.c | 225 +-------------------------------------
 3 files changed, 237 insertions(+), 223 deletions(-)

diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
index 81101775fed0..e1d765a7372c 100644
--- a/drivers/rpmsg/rpmsg_core.c
+++ b/drivers/rpmsg/rpmsg_core.c
@@ -262,3 +262,234 @@ struct device *rpmsg_find_device(struct device *parent,
 
 }
 EXPORT_SYMBOL(rpmsg_find_device);
+
+/* 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_channel_info chinfo = {};
+	struct rpmsg_endpoint *ept;
+	int err;
+
+	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;
+		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->ops->announce_create)
+		err = rpdev->ops->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->ops->announce_destroy)
+		err = rpdev->ops->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);
+
+/*
+ * 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
index 205debf4ea65..8ac98fd0bf1d 100644
--- a/drivers/rpmsg/rpmsg_internal.h
+++ b/drivers/rpmsg/rpmsg_internal.h
@@ -25,6 +25,10 @@
 #define to_rpmsg_device(d) container_of(d, struct rpmsg_device, dev)
 #define to_rpmsg_driver(d) container_of(d, struct rpmsg_driver, drv)
 
+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);
 
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index e1052622c6a2..31cd526f690d 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -75,9 +75,6 @@ struct virtproc_info {
 	struct rpmsg_endpoint *ns_ept;
 };
 
-#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
@@ -120,72 +117,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);
-}
 
 static const struct rpmsg_endpoint_ops virtio_endpoint_ops = {
 	.destroy_ept = virtio_rpmsg_destroy_ept,
@@ -307,49 +238,6 @@ 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_channel_info chinfo = {};
-	struct rpmsg_endpoint *ept;
-	int err;
-
-	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;
-		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->ops->announce_create)
-		err = rpdev->ops->announce_create(rpdev);
-out:
-	return err;
-}
-
 static int virtio_rpmsg_announce_create(struct rpmsg_device *rpdev)
 {
 	struct virtproc_info *vrp = rpdev->vrp;
@@ -396,65 +284,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->ops->announce_destroy)
-		err = rpdev->ops->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);
-}
-
 static const struct rpmsg_device_ops virtio_rpmsg_ops = {
 	.create_ept = virtio_rpmsg_create_ept,
 	.announce_create = virtio_rpmsg_announce_create,
@@ -508,47 +337,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 = rpmsg_find_device(&vdev->dev, chinfo);
-	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)
 {
@@ -967,7 +755,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 {
@@ -1152,17 +940,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;
 }
@@ -1171,7 +951,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] 68+ messages in thread

* [PATCH v2 13/17] rpmsg: Hide rpmsg indirection tables
  2016-09-01 22:27 ` Bjorn Andersson
@ 2016-09-01 22:28   ` Bjorn Andersson
  -1 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:28 UTC (permalink / raw)
  To: Ohad Ben-Cohen, Bjorn Andersson
  Cc: linux-remoteproc, linux-arm-msm, linux-arm-kernel, linux-kernel

Move the device and endpoint indirection tables to the rpmsg internal
header file, to hide them from the public API.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---

Changes since v1:
- None

 drivers/rpmsg/rpmsg_core.c     |  3 +++
 drivers/rpmsg/rpmsg_internal.h | 47 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/rpmsg.h          | 47 ------------------------------------------
 3 files changed, 50 insertions(+), 47 deletions(-)

diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
index e1d765a7372c..b6ea9ffa7381 100644
--- a/drivers/rpmsg/rpmsg_core.c
+++ b/drivers/rpmsg/rpmsg_core.c
@@ -20,7 +20,10 @@
 #define pr_fmt(fmt) "%s: " fmt, __func__
 
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/rpmsg.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
 
 #include "rpmsg_internal.h"
 
diff --git a/drivers/rpmsg/rpmsg_internal.h b/drivers/rpmsg/rpmsg_internal.h
index 8ac98fd0bf1d..8075a20f919b 100644
--- a/drivers/rpmsg/rpmsg_internal.h
+++ b/drivers/rpmsg/rpmsg_internal.h
@@ -25,6 +25,53 @@
 #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_device_ops - indirection table for the rpmsg_device operations
+ * @create_ept:		create backend-specific endpoint, requried
+ * @announce_create:	announce presence of new channel, optional
+ * @announce_destroy:	announce destruction of channel, optional
+ *
+ * Indirection table for the operations that a rpmsg backend should implement.
+ * @announce_create and @announce_destroy are optional as the backend might
+ * advertise new channels implicitly by creating the endpoints.
+ */
+struct rpmsg_device_ops {
+	struct rpmsg_endpoint *(*create_ept)(struct rpmsg_device *rpdev,
+					    rpmsg_rx_cb_t cb, void *priv,
+					    struct rpmsg_channel_info chinfo);
+
+	int (*announce_create)(struct rpmsg_device *ept);
+	int (*announce_destroy)(struct rpmsg_device *ept);
+};
+
+/**
+ * struct rpmsg_endpoint_ops - indirection table for rpmsg_endpoint operations
+ * @destroy_ept:	destroy the given endpoint, required
+ * @send:		see @rpmsg_send(), required
+ * @sendto:		see @rpmsg_sendto(), optional
+ * @send_offchannel:	see @rpmsg_send_offchannel(), optional
+ * @trysend:		see @rpmsg_trysend(), required
+ * @trysendto:		see @rpmsg_trysendto(), optional
+ * @trysend_offchannel:	see @rpmsg_trysend_offchannel(), optional
+ *
+ * Indirection table for the operations that a rpmsg backend should implement.
+ * In addition to @destroy_ept, the backend must at least implement @send and
+ * @trysend, while the variants sending data off-channel are optional.
+ */
+struct rpmsg_endpoint_ops {
+	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 rpmsg_register_device(struct rpmsg_device *rpdev);
 int rpmsg_unregister_device(struct device *parent,
 			    struct rpmsg_channel_info *chinfo);
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index 99efd598590e..4f9445f71f2f 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -138,25 +138,6 @@ struct rpmsg_device {
 typedef void (*rpmsg_rx_cb_t)(struct rpmsg_device *, void *, int, void *, u32);
 
 /**
- * struct rpmsg_device_ops - indirection table for the rpmsg_device operations
- * @create_ept:		create backend-specific endpoint, requried
- * @announce_create:	announce presence of new channel, optional
- * @announce_destroy:	announce destruction of channel, optional
- *
- * Indirection table for the operations that a rpmsg backend should implement.
- * @announce_create and @announce_destroy are optional as the backend might
- * advertise new channels implicitly by creating the endpoints.
- */
-struct rpmsg_device_ops {
-	struct rpmsg_endpoint *(*create_ept)(struct rpmsg_device *rpdev,
-					    rpmsg_rx_cb_t cb, void *priv,
-					    struct rpmsg_channel_info chinfo);
-
-	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
  * @rpdev: rpmsg channel device
  * @refcount: when this drops to zero, the ept is deallocated
@@ -191,34 +172,6 @@ struct rpmsg_endpoint {
 };
 
 /**
- * struct rpmsg_endpoint_ops - indirection table for rpmsg_endpoint operations
- * @destroy_ept:	destroy the given endpoint, required
- * @send:		see @rpmsg_send(), required
- * @sendto:		see @rpmsg_sendto(), optional
- * @send_offchannel:	see @rpmsg_send_offchannel(), optional
- * @trysend:		see @rpmsg_trysend(), required
- * @trysendto:		see @rpmsg_trysendto(), optional
- * @trysend_offchannel:	see @rpmsg_trysend_offchannel(), optional
- *
- * Indirection table for the operations that a rpmsg backend should implement.
- * In addition to @destroy_ept, the backend must at least implement @send and
- * @trysend, while the variants sending data off-channel are optional.
- */
-struct rpmsg_endpoint_ops {
-	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);
-};
-
-/**
  * struct rpmsg_driver - rpmsg driver struct
  * @drv: underlying device driver
  * @id_table: rpmsg ids serviced by this driver
-- 
2.5.0

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

* [PATCH v2 13/17] rpmsg: Hide rpmsg indirection tables
@ 2016-09-01 22:28   ` Bjorn Andersson
  0 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:28 UTC (permalink / raw)
  To: linux-arm-kernel

Move the device and endpoint indirection tables to the rpmsg internal
header file, to hide them from the public API.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---

Changes since v1:
- None

 drivers/rpmsg/rpmsg_core.c     |  3 +++
 drivers/rpmsg/rpmsg_internal.h | 47 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/rpmsg.h          | 47 ------------------------------------------
 3 files changed, 50 insertions(+), 47 deletions(-)

diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
index e1d765a7372c..b6ea9ffa7381 100644
--- a/drivers/rpmsg/rpmsg_core.c
+++ b/drivers/rpmsg/rpmsg_core.c
@@ -20,7 +20,10 @@
 #define pr_fmt(fmt) "%s: " fmt, __func__
 
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/rpmsg.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
 
 #include "rpmsg_internal.h"
 
diff --git a/drivers/rpmsg/rpmsg_internal.h b/drivers/rpmsg/rpmsg_internal.h
index 8ac98fd0bf1d..8075a20f919b 100644
--- a/drivers/rpmsg/rpmsg_internal.h
+++ b/drivers/rpmsg/rpmsg_internal.h
@@ -25,6 +25,53 @@
 #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_device_ops - indirection table for the rpmsg_device operations
+ * @create_ept:		create backend-specific endpoint, requried
+ * @announce_create:	announce presence of new channel, optional
+ * @announce_destroy:	announce destruction of channel, optional
+ *
+ * Indirection table for the operations that a rpmsg backend should implement.
+ * @announce_create and @announce_destroy are optional as the backend might
+ * advertise new channels implicitly by creating the endpoints.
+ */
+struct rpmsg_device_ops {
+	struct rpmsg_endpoint *(*create_ept)(struct rpmsg_device *rpdev,
+					    rpmsg_rx_cb_t cb, void *priv,
+					    struct rpmsg_channel_info chinfo);
+
+	int (*announce_create)(struct rpmsg_device *ept);
+	int (*announce_destroy)(struct rpmsg_device *ept);
+};
+
+/**
+ * struct rpmsg_endpoint_ops - indirection table for rpmsg_endpoint operations
+ * @destroy_ept:	destroy the given endpoint, required
+ * @send:		see @rpmsg_send(), required
+ * @sendto:		see @rpmsg_sendto(), optional
+ * @send_offchannel:	see @rpmsg_send_offchannel(), optional
+ * @trysend:		see @rpmsg_trysend(), required
+ * @trysendto:		see @rpmsg_trysendto(), optional
+ * @trysend_offchannel:	see @rpmsg_trysend_offchannel(), optional
+ *
+ * Indirection table for the operations that a rpmsg backend should implement.
+ * In addition to @destroy_ept, the backend must at least implement @send and
+ * @trysend, while the variants sending data off-channel are optional.
+ */
+struct rpmsg_endpoint_ops {
+	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 rpmsg_register_device(struct rpmsg_device *rpdev);
 int rpmsg_unregister_device(struct device *parent,
 			    struct rpmsg_channel_info *chinfo);
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index 99efd598590e..4f9445f71f2f 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -138,25 +138,6 @@ struct rpmsg_device {
 typedef void (*rpmsg_rx_cb_t)(struct rpmsg_device *, void *, int, void *, u32);
 
 /**
- * struct rpmsg_device_ops - indirection table for the rpmsg_device operations
- * @create_ept:		create backend-specific endpoint, requried
- * @announce_create:	announce presence of new channel, optional
- * @announce_destroy:	announce destruction of channel, optional
- *
- * Indirection table for the operations that a rpmsg backend should implement.
- * @announce_create and @announce_destroy are optional as the backend might
- * advertise new channels implicitly by creating the endpoints.
- */
-struct rpmsg_device_ops {
-	struct rpmsg_endpoint *(*create_ept)(struct rpmsg_device *rpdev,
-					    rpmsg_rx_cb_t cb, void *priv,
-					    struct rpmsg_channel_info chinfo);
-
-	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
  * @rpdev: rpmsg channel device
  * @refcount: when this drops to zero, the ept is deallocated
@@ -191,34 +172,6 @@ struct rpmsg_endpoint {
 };
 
 /**
- * struct rpmsg_endpoint_ops - indirection table for rpmsg_endpoint operations
- * @destroy_ept:	destroy the given endpoint, required
- * @send:		see @rpmsg_send(), required
- * @sendto:		see @rpmsg_sendto(), optional
- * @send_offchannel:	see @rpmsg_send_offchannel(), optional
- * @trysend:		see @rpmsg_trysend(), required
- * @trysendto:		see @rpmsg_trysendto(), optional
- * @trysend_offchannel:	see @rpmsg_trysend_offchannel(), optional
- *
- * Indirection table for the operations that a rpmsg backend should implement.
- * In addition to @destroy_ept, the backend must at least implement @send and
- * @trysend, while the variants sending data off-channel are optional.
- */
-struct rpmsg_endpoint_ops {
-	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);
-};
-
-/**
  * struct rpmsg_driver - rpmsg driver struct
  * @drv: underlying device driver
  * @id_table: rpmsg ids serviced by this driver
-- 
2.5.0

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

* [PATCH v2 14/17] rpmsg: virtio: Hide vrp pointer from the public API
  2016-09-01 22:27 ` Bjorn Andersson
@ 2016-09-01 22:28   ` Bjorn Andersson
  -1 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:28 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. This makes the public structures independant of virtio.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---

Changes since v1:
- Reduced complexity from the move of ops to the public structs

 drivers/rpmsg/virtio_rpmsg_bus.c | 43 ++++++++++++++++++++++++++++++++--------
 include/linux/rpmsg.h            |  3 ---
 2 files changed, 35 insertions(+), 11 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 31cd526f690d..ac2241242188 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -75,6 +75,18 @@ struct virtproc_info {
 	struct rpmsg_endpoint *ns_ept;
 };
 
+/**
+ * @vrp: the remote processor this channel belongs to
+ */
+struct virtio_rpmsg_channel {
+	struct rpmsg_device rpdev;
+
+	struct virtproc_info *vrp;
+};
+
+#define to_virtio_rpmsg_channel(_rpdev) \
+	container_of(_rpdev, struct virtio_rpmsg_channel, rpdev)
+
 /*
  * We're allocating buffers of 512 bytes each for communications. The
  * number of buffers will be computed from the number of buffers supported
@@ -204,7 +216,9 @@ static struct rpmsg_endpoint *virtio_rpmsg_create_ept(struct rpmsg_device *rpdev
 						      void *priv,
 						      struct rpmsg_channel_info chinfo)
 {
-	return __rpmsg_create_ept(rpdev->vrp, rpdev, cb, priv, chinfo.src);
+	struct virtio_rpmsg_channel *vch = to_virtio_rpmsg_channel(rpdev);
+
+	return __rpmsg_create_ept(vch->vrp, rpdev, cb, priv, chinfo.src);
 }
 
 /**
@@ -235,12 +249,15 @@ __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);
+
+	__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);
+	struct virtproc_info *vrp = vch->vrp;
 	struct device *dev = &rpdev->dev;
 	int err = 0;
 
@@ -263,7 +280,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);
+	struct virtproc_info *vrp = vch->vrp;
 	struct device *dev = &rpdev->dev;
 	int err = 0;
 
@@ -298,6 +316,7 @@ static const struct rpmsg_device_ops virtio_rpmsg_ops = {
 static struct rpmsg_device *rpmsg_create_channel(struct virtproc_info *vrp,
 						 struct rpmsg_channel_info *chinfo)
 {
+	struct virtio_rpmsg_channel *vch;
 	struct rpmsg_device *rpdev;
 	struct device *tmp, *dev = &vrp->vdev->dev;
 	int ret;
@@ -312,11 +331,18 @@ static struct rpmsg_device *rpmsg_create_channel(struct virtproc_info *vrp,
 		return NULL;
 	}
 
-	rpdev = kzalloc(sizeof(*rpdev), GFP_KERNEL);
-	if (!rpdev)
+	vch = kzalloc(sizeof(*vch), GFP_KERNEL);
+	if (!vch)
 		return NULL;
 
-	rpdev->vrp = vrp;
+	/* Link the channel to our vrp */
+	vch->vrp = vrp;
+
+	/* Assign callbacks for rpmsg_channel */
+	vch->rpdev.ops = &virtio_rpmsg_ops;
+
+	/* Assign public information to the rpmsg_device */
+	rpdev = &vch->rpdev;
 	rpdev->src = chinfo->src;
 	rpdev->dst = chinfo->dst;
 	rpdev->ops = &virtio_rpmsg_ops;
@@ -455,7 +481,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);
+	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 4f9445f71f2f..b4b56b010f71 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;
 struct rpmsg_device_ops;
@@ -115,7 +114,6 @@ struct rpmsg_channel_info {
 
 /**
  * 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
@@ -124,7 +122,6 @@ struct rpmsg_channel_info {
  * @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] 68+ messages in thread

* [PATCH v2 14/17] rpmsg: virtio: Hide vrp pointer from the public API
@ 2016-09-01 22:28   ` Bjorn Andersson
  0 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:28 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. This makes the public structures independant of virtio.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---

Changes since v1:
- Reduced complexity from the move of ops to the public structs

 drivers/rpmsg/virtio_rpmsg_bus.c | 43 ++++++++++++++++++++++++++++++++--------
 include/linux/rpmsg.h            |  3 ---
 2 files changed, 35 insertions(+), 11 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 31cd526f690d..ac2241242188 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -75,6 +75,18 @@ struct virtproc_info {
 	struct rpmsg_endpoint *ns_ept;
 };
 
+/**
+ * @vrp: the remote processor this channel belongs to
+ */
+struct virtio_rpmsg_channel {
+	struct rpmsg_device rpdev;
+
+	struct virtproc_info *vrp;
+};
+
+#define to_virtio_rpmsg_channel(_rpdev) \
+	container_of(_rpdev, struct virtio_rpmsg_channel, rpdev)
+
 /*
  * We're allocating buffers of 512 bytes each for communications. The
  * number of buffers will be computed from the number of buffers supported
@@ -204,7 +216,9 @@ static struct rpmsg_endpoint *virtio_rpmsg_create_ept(struct rpmsg_device *rpdev
 						      void *priv,
 						      struct rpmsg_channel_info chinfo)
 {
-	return __rpmsg_create_ept(rpdev->vrp, rpdev, cb, priv, chinfo.src);
+	struct virtio_rpmsg_channel *vch = to_virtio_rpmsg_channel(rpdev);
+
+	return __rpmsg_create_ept(vch->vrp, rpdev, cb, priv, chinfo.src);
 }
 
 /**
@@ -235,12 +249,15 @@ __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);
+
+	__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);
+	struct virtproc_info *vrp = vch->vrp;
 	struct device *dev = &rpdev->dev;
 	int err = 0;
 
@@ -263,7 +280,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);
+	struct virtproc_info *vrp = vch->vrp;
 	struct device *dev = &rpdev->dev;
 	int err = 0;
 
@@ -298,6 +316,7 @@ static const struct rpmsg_device_ops virtio_rpmsg_ops = {
 static struct rpmsg_device *rpmsg_create_channel(struct virtproc_info *vrp,
 						 struct rpmsg_channel_info *chinfo)
 {
+	struct virtio_rpmsg_channel *vch;
 	struct rpmsg_device *rpdev;
 	struct device *tmp, *dev = &vrp->vdev->dev;
 	int ret;
@@ -312,11 +331,18 @@ static struct rpmsg_device *rpmsg_create_channel(struct virtproc_info *vrp,
 		return NULL;
 	}
 
-	rpdev = kzalloc(sizeof(*rpdev), GFP_KERNEL);
-	if (!rpdev)
+	vch = kzalloc(sizeof(*vch), GFP_KERNEL);
+	if (!vch)
 		return NULL;
 
-	rpdev->vrp = vrp;
+	/* Link the channel to our vrp */
+	vch->vrp = vrp;
+
+	/* Assign callbacks for rpmsg_channel */
+	vch->rpdev.ops = &virtio_rpmsg_ops;
+
+	/* Assign public information to the rpmsg_device */
+	rpdev = &vch->rpdev;
 	rpdev->src = chinfo->src;
 	rpdev->dst = chinfo->dst;
 	rpdev->ops = &virtio_rpmsg_ops;
@@ -455,7 +481,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);
+	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 4f9445f71f2f..b4b56b010f71 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;
 struct rpmsg_device_ops;
@@ -115,7 +114,6 @@ struct rpmsg_channel_info {
 
 /**
  * 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
@@ -124,7 +122,6 @@ struct rpmsg_channel_info {
  * @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] 68+ messages in thread

* [PATCH v2 15/17] rpmsg: Move virtio specifics from public header
  2016-09-01 22:27 ` Bjorn Andersson
@ 2016-09-01 22:28   ` Bjorn Andersson
  -1 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:28 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>
---

Changes since v1:
- None

 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 ac2241242188..671cb1803431 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 b4b56b010f71..71b16d37503a 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] 68+ messages in thread

* [PATCH v2 15/17] rpmsg: Move virtio specifics from public header
@ 2016-09-01 22:28   ` Bjorn Andersson
  0 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:28 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>
---

Changes since v1:
- None

 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 ac2241242188..671cb1803431 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 b4b56b010f71..71b16d37503a 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] 68+ messages in thread

* [PATCH v2 16/17] rpmsg: Allow callback to return errors
  2016-09-01 22:27 ` Bjorn Andersson
@ 2016-09-01 22:28   ` Bjorn Andersson
  -1 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:28 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>
---

Changes since v1:
- None

 drivers/rpmsg/virtio_rpmsg_bus.c    | 10 ++++++----
 include/linux/rpmsg.h               |  4 ++--
 samples/rpmsg/rpmsg_client_sample.c |  6 ++++--
 3 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 671cb1803431..3090b0d3072f 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -791,8 +791,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;
@@ -808,7 +808,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;
 	}
 
 	/*
@@ -819,7 +819,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 */
@@ -842,6 +842,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 71b16d37503a..452d393cc8dd 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -80,7 +80,7 @@ struct rpmsg_device {
 	const struct rpmsg_device_ops *ops;
 };
 
-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_endpoint - binds a local rpmsg address to its user
@@ -129,7 +129,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);
diff --git a/samples/rpmsg/rpmsg_client_sample.c b/samples/rpmsg/rpmsg_client_sample.c
index 4fcd7ee13fb9..f161dfd3e70a 100644
--- a/samples/rpmsg/rpmsg_client_sample.c
+++ b/samples/rpmsg/rpmsg_client_sample.c
@@ -28,7 +28,7 @@ struct instance_data {
 	int rx_count;
 };
 
-static void rpmsg_sample_cb(struct rpmsg_device *rpdev, void *data, int len,
+static int rpmsg_sample_cb(struct rpmsg_device *rpdev, void *data, int len,
 						void *priv, u32 src)
 {
 	int ret;
@@ -43,13 +43,15 @@ static void rpmsg_sample_cb(struct rpmsg_device *rpdev, void *data, int len,
 	/* samples should not live forever */
 	if (idata->rx_count >= MSG_LIMIT) {
 		dev_info(&rpdev->dev, "goodbye!\n");
-		return;
+		return 0;
 	}
 
 	/* send a new message now */
 	ret = rpmsg_send(rpdev->ept, MSG, strlen(MSG));
 	if (ret)
 		dev_err(&rpdev->dev, "rpmsg_send failed: %d\n", ret);
+
+	return 0;
 }
 
 static int rpmsg_sample_probe(struct rpmsg_device *rpdev)
-- 
2.5.0

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

* [PATCH v2 16/17] rpmsg: Allow callback to return errors
@ 2016-09-01 22:28   ` Bjorn Andersson
  0 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:28 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>
---

Changes since v1:
- None

 drivers/rpmsg/virtio_rpmsg_bus.c    | 10 ++++++----
 include/linux/rpmsg.h               |  4 ++--
 samples/rpmsg/rpmsg_client_sample.c |  6 ++++--
 3 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 671cb1803431..3090b0d3072f 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -791,8 +791,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;
@@ -808,7 +808,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;
 	}
 
 	/*
@@ -819,7 +819,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 */
@@ -842,6 +842,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 71b16d37503a..452d393cc8dd 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -80,7 +80,7 @@ struct rpmsg_device {
 	const struct rpmsg_device_ops *ops;
 };
 
-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_endpoint - binds a local rpmsg address to its user
@@ -129,7 +129,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);
diff --git a/samples/rpmsg/rpmsg_client_sample.c b/samples/rpmsg/rpmsg_client_sample.c
index 4fcd7ee13fb9..f161dfd3e70a 100644
--- a/samples/rpmsg/rpmsg_client_sample.c
+++ b/samples/rpmsg/rpmsg_client_sample.c
@@ -28,7 +28,7 @@ struct instance_data {
 	int rx_count;
 };
 
-static void rpmsg_sample_cb(struct rpmsg_device *rpdev, void *data, int len,
+static int rpmsg_sample_cb(struct rpmsg_device *rpdev, void *data, int len,
 						void *priv, u32 src)
 {
 	int ret;
@@ -43,13 +43,15 @@ static void rpmsg_sample_cb(struct rpmsg_device *rpdev, void *data, int len,
 	/* samples should not live forever */
 	if (idata->rx_count >= MSG_LIMIT) {
 		dev_info(&rpdev->dev, "goodbye!\n");
-		return;
+		return 0;
 	}
 
 	/* send a new message now */
 	ret = rpmsg_send(rpdev->ept, MSG, strlen(MSG));
 	if (ret)
 		dev_err(&rpdev->dev, "rpmsg_send failed: %d\n", ret);
+
+	return 0;
 }
 
 static int rpmsg_sample_probe(struct rpmsg_device *rpdev)
-- 
2.5.0

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

* [PATCH v2 17/17] rpmsg: Introduce Qualcomm SMD backend
  2016-09-01 22:27 ` Bjorn Andersson
@ 2016-09-01 22:28   ` Bjorn Andersson
  -1 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:28 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>
---

Changes since v1:
- Rebased from latest linux-next version of SMD

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

diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig
index 40614be88c97..9ba5a2e5c930 100644
--- a/drivers/rpmsg/Kconfig
+++ b/drivers/rpmsg/Kconfig
@@ -4,6 +4,16 @@ menu "Rpmsg drivers"
 config RPMSG
 	tristate
 
+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.
+
 config RPMSG_VIRTIO
 	tristate
 	select RPMSG
diff --git a/drivers/rpmsg/Makefile b/drivers/rpmsg/Makefile
index c48ea55ad380..ae9c9132cf76 100644
--- a/drivers/rpmsg/Makefile
+++ b/drivers/rpmsg/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_RPMSG)		+= rpmsg_core.o
+obj-$(CONFIG_RPMSG_QCOM_SMD)	+= qcom_smd.o
 obj-$(CONFIG_RPMSG_VIRTIO)	+= virtio_rpmsg_bus.o
diff --git a/drivers/rpmsg/qcom_smd.c b/drivers/rpmsg/qcom_smd.c
new file mode 100644
index 000000000000..06fef2b4c814
--- /dev/null
+++ b/drivers/rpmsg/qcom_smd.c
@@ -0,0 +1,1434 @@
+/*
+ * 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;
+
+static const struct rpmsg_endpoint_ops qcom_smd_endpoint_ops;
+
+#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_device rpdev;
+
+	struct qcom_smd_edge *edge;
+};
+
+struct qcom_smd_endpoint {
+	struct rpmsg_endpoint ept;
+
+	struct qcom_smd_channel *qsch;
+};
+
+#define to_smd_device(_rpdev)	container_of(_rpdev, struct qcom_smd_device, rpdev)
+#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_RX_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;
+}
+
+/*
+ * 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);
+	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;
+	ept->ops = &qcom_smd_endpoint_ops;
+
+	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_device_ops qcom_smd_device_ops = {
+	.create_ept = qcom_smd_create_ept,
+};
+
+static const struct rpmsg_endpoint_ops qcom_smd_endpoint_ops = {
+	.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_device */
+	qsdev->rpdev.ops = &qcom_smd_device_ops;
+
+	/* Assign public information to the rpmsg_device */
+	rpdev = &qsdev->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] 68+ messages in thread

* [PATCH v2 17/17] rpmsg: Introduce Qualcomm SMD backend
@ 2016-09-01 22:28   ` Bjorn Andersson
  0 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-01 22:28 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>
---

Changes since v1:
- Rebased from latest linux-next version of SMD

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

diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig
index 40614be88c97..9ba5a2e5c930 100644
--- a/drivers/rpmsg/Kconfig
+++ b/drivers/rpmsg/Kconfig
@@ -4,6 +4,16 @@ menu "Rpmsg drivers"
 config RPMSG
 	tristate
 
+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.
+
 config RPMSG_VIRTIO
 	tristate
 	select RPMSG
diff --git a/drivers/rpmsg/Makefile b/drivers/rpmsg/Makefile
index c48ea55ad380..ae9c9132cf76 100644
--- a/drivers/rpmsg/Makefile
+++ b/drivers/rpmsg/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_RPMSG)		+= rpmsg_core.o
+obj-$(CONFIG_RPMSG_QCOM_SMD)	+= qcom_smd.o
 obj-$(CONFIG_RPMSG_VIRTIO)	+= virtio_rpmsg_bus.o
diff --git a/drivers/rpmsg/qcom_smd.c b/drivers/rpmsg/qcom_smd.c
new file mode 100644
index 000000000000..06fef2b4c814
--- /dev/null
+++ b/drivers/rpmsg/qcom_smd.c
@@ -0,0 +1,1434 @@
+/*
+ * 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;
+
+static const struct rpmsg_endpoint_ops qcom_smd_endpoint_ops;
+
+#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_device rpdev;
+
+	struct qcom_smd_edge *edge;
+};
+
+struct qcom_smd_endpoint {
+	struct rpmsg_endpoint ept;
+
+	struct qcom_smd_channel *qsch;
+};
+
+#define to_smd_device(_rpdev)	container_of(_rpdev, struct qcom_smd_device, rpdev)
+#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_RX_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;
+}
+
+/*
+ * 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);
+	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;
+	ept->ops = &qcom_smd_endpoint_ops;
+
+	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_device_ops qcom_smd_device_ops = {
+	.create_ept = qcom_smd_create_ept,
+};
+
+static const struct rpmsg_endpoint_ops qcom_smd_endpoint_ops = {
+	.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_device */
+	qsdev->rpdev.ops = &qcom_smd_device_ops;
+
+	/* Assign public information to the rpmsg_device */
+	rpdev = &qsdev->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] 68+ messages in thread

* Re: [PATCH v2 01/17] rpmsg: Enable matching devices with drivers based on DT
  2016-09-01 22:27   ` Bjorn Andersson
@ 2016-09-08  1:46     ` spjoshi at codeaurora.org
  -1 siblings, 0 replies; 68+ messages in thread
From: spjoshi @ 2016-09-08  1:46 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Ohad Ben-Cohen, linux-remoteproc, linux-arm-msm,
	linux-arm-kernel, linux-kernel, linux-remoteproc-owner

On 2016-09-01 15:27, Bjorn Andersson wrote:
> 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>
> ---
> 
> Changes since v1:
> - None
> 
>  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);

Do we care falling back to acpi_driver_match_device if 
of_driver_match_device fails (something similar to what platform_match 
does)?

>  }
> 
>  static int rpmsg_uevent(struct device *dev, struct kobj_uevent_env 
> *env)

Sarang

--
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* [PATCH v2 01/17] rpmsg: Enable matching devices with drivers based on DT
@ 2016-09-08  1:46     ` spjoshi at codeaurora.org
  0 siblings, 0 replies; 68+ messages in thread
From: spjoshi at codeaurora.org @ 2016-09-08  1:46 UTC (permalink / raw)
  To: linux-arm-kernel

On 2016-09-01 15:27, Bjorn Andersson wrote:
> 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>
> ---
> 
> Changes since v1:
> - None
> 
>  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);

Do we care falling back to acpi_driver_match_device if 
of_driver_match_device fails (something similar to what platform_match 
does)?

>  }
> 
>  static int rpmsg_uevent(struct device *dev, struct kobj_uevent_env 
> *env)

Sarang

--
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* Re: [PATCH v2 02/17] rpmsg: Name rpmsg devices based on channel id
  2016-09-01 22:27   ` Bjorn Andersson
@ 2016-09-08  1:46     ` spjoshi at codeaurora.org
  -1 siblings, 0 replies; 68+ messages in thread
From: spjoshi @ 2016-09-08  1:46 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Ohad Ben-Cohen, linux-arm-msm, linux-remoteproc, linux-kernel,
	linux-arm-kernel

On 2016-09-01 15:27, Bjorn Andersson wrote:
> 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>
> ---
> 
> Changes since v1:
> - None
> 
>  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;

Reviewed-by: Sarangdhar Joshi <spjoshi@codeaurora.org>

Sarang

--
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* [PATCH v2 02/17] rpmsg: Name rpmsg devices based on channel id
@ 2016-09-08  1:46     ` spjoshi at codeaurora.org
  0 siblings, 0 replies; 68+ messages in thread
From: spjoshi at codeaurora.org @ 2016-09-08  1:46 UTC (permalink / raw)
  To: linux-arm-kernel

On 2016-09-01 15:27, Bjorn Andersson wrote:
> 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>
> ---
> 
> Changes since v1:
> - None
> 
>  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;

Reviewed-by: Sarangdhar Joshi <spjoshi@codeaurora.org>

Sarang

--
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* Re: [PATCH v2 01/17] rpmsg: Enable matching devices with drivers based on DT
  2016-09-08  1:46     ` spjoshi at codeaurora.org
@ 2016-09-09  4:30       ` Bjorn Andersson
  -1 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-09  4:30 UTC (permalink / raw)
  To: spjoshi
  Cc: Ohad Ben-Cohen, linux-remoteproc, linux-arm-msm,
	linux-arm-kernel, linux-kernel, linux-remoteproc-owner

On Wed 07 Sep 18:46 PDT 2016, spjoshi@codeaurora.org wrote:

> On 2016-09-01 15:27, Bjorn Andersson wrote:
> >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>
> >---
> >
> >Changes since v1:
> >- None
> >
> > 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);
> 
> Do we care falling back to acpi_driver_match_device if
> of_driver_match_device fails (something similar to what platform_match
> does)?
> 

I'm not sure how this would look in the case of ACPI, so I would prefer
if we defer that until such case arise.

Regards,
Bjorn

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

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

On Wed 07 Sep 18:46 PDT 2016, spjoshi at codeaurora.org wrote:

> On 2016-09-01 15:27, Bjorn Andersson wrote:
> >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>
> >---
> >
> >Changes since v1:
> >- None
> >
> > 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);
> 
> Do we care falling back to acpi_driver_match_device if
> of_driver_match_device fails (something similar to what platform_match
> does)?
> 

I'm not sure how this would look in the case of ACPI, so I would prefer
if we defer that until such case arise.

Regards,
Bjorn

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

* Re: [PATCH v2 01/17] rpmsg: Enable matching devices with drivers based on DT
  2016-09-09  4:30       ` Bjorn Andersson
@ 2016-09-09 22:07         ` Sarangdhar Joshi
  -1 siblings, 0 replies; 68+ messages in thread
From: Sarangdhar Joshi @ 2016-09-09 22:07 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Ohad Ben-Cohen, linux-remoteproc, linux-arm-msm,
	linux-arm-kernel, linux-kernel, linux-remoteproc-owner

On 09/08/2016 09:30 PM, Bjorn Andersson wrote:
> On Wed 07 Sep 18:46 PDT 2016, spjoshi@codeaurora.org wrote:
>
>> On 2016-09-01 15:27, Bjorn Andersson wrote:
>>> 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>
>>> ---
>>>
>>> Changes since v1:
>>> - None
>>>
>>> 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);
>>
>> Do we care falling back to acpi_driver_match_device if
>> of_driver_match_device fails (something similar to what platform_match
>> does)?
>>
>
> I'm not sure how this would look in the case of ACPI, so I would prefer
> if we defer that until such case arise.

Makes sense.

>
> Regards,
> Bjorn
>

Adding Reviewed-by tag:

Reviewed-by: Sarangdhar Joshi <spjoshi@codeaurora.org>

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* [PATCH v2 01/17] rpmsg: Enable matching devices with drivers based on DT
@ 2016-09-09 22:07         ` Sarangdhar Joshi
  0 siblings, 0 replies; 68+ messages in thread
From: Sarangdhar Joshi @ 2016-09-09 22:07 UTC (permalink / raw)
  To: linux-arm-kernel

On 09/08/2016 09:30 PM, Bjorn Andersson wrote:
> On Wed 07 Sep 18:46 PDT 2016, spjoshi at codeaurora.org wrote:
>
>> On 2016-09-01 15:27, Bjorn Andersson wrote:
>>> 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>
>>> ---
>>>
>>> Changes since v1:
>>> - None
>>>
>>> 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);
>>
>> Do we care falling back to acpi_driver_match_device if
>> of_driver_match_device fails (something similar to what platform_match
>> does)?
>>
>
> I'm not sure how this would look in the case of ACPI, so I would prefer
> if we defer that until such case arise.

Makes sense.

>
> Regards,
> Bjorn
>

Adding Reviewed-by tag:

Reviewed-by: Sarangdhar Joshi <spjoshi@codeaurora.org>

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* Re: [PATCH v2 00/17] Make rpmsg a framework
  2016-09-01 22:27 ` Bjorn Andersson
@ 2016-09-12 16:52   ` Lina Iyer
  -1 siblings, 0 replies; 68+ messages in thread
From: Lina Iyer @ 2016-09-12 16:52 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Ohad Ben-Cohen, linux-remoteproc, linux-arm-msm,
	linux-arm-kernel, linux-kernel

Hi Bjorn,

On Thu, Sep 01 2016 at 16:28 -0600, Bjorn Andersson wrote:
>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.
>

RPM Communication has to supported even when IRQs are disabled. The most
important use of this communication is to set the wake up time for the
CPU subsystem when all the CPUs are powered off. In addition to that,
"sleep" votes that are sent by the application processor subsystem to
allow system to go into deep sleep modes can only be triggered when the
CPU PM domains are power collapsed, drivers do not have a knowledge of
when that happens. This has to be done by a platform code that registers
for CPU PM domain power_off/on callbacks.

Using rpmsg may be nice for RPM SMD communication, but mutexes need to
go away for this driver to be any useful than bare bones active mode
resource requests for QCOM SoCs. By not doing that now, we lock
ourselves out of using this SMD driver in the near future when CPU PM
domains are available in the kernel with an ability to do system low
power modes.

I hope you would make rpmsg work in IRQ disabled contexts first before
porting the SMD driver.

Thanks,
Lina

>
>Changes from v1:
>- Split up the patch moving core code to rpmsg_core into several commits
>- Dropped the wrapping struct in rpmsg_core and just added the ops to the
>  public API (but hid the implementation details)
>- Reordered things to reduce the size of the later patches
>
>Bjorn Andersson (17):
>  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: Make rpmsg_create_ept() take channel_info struct
>  rpmsg: Clean up rpmsg device vs channel naming
>  rpmsg: Introduce indirection table for rpmsg_device operations
>  rpmsg: Move rpmsg_device API to new file
>  rpmsg: Indirection table for rpmsg_endpoint operations
>  rpmsg: Move endpoint related interface to rpmsg core
>  rpmsg: Move helper for finding rpmsg devices to core
>  rpmsg: Split off generic tail of create_channel()
>  rpmsg: Split rpmsg core and virtio backend
>  rpmsg: Hide rpmsg indirection tables
>  rpmsg: virtio: Hide vrp pointer from the public API
>  rpmsg: Move virtio specifics from public header
>  rpmsg: Allow callback to return errors
>  rpmsg: Introduce Qualcomm SMD backend
>
> drivers/remoteproc/Kconfig          |    4 +-
> drivers/rpmsg/Kconfig               |   14 +
> drivers/rpmsg/Makefile              |    4 +-
> drivers/rpmsg/qcom_smd.c            | 1434 +++++++++++++++++++++++++++++++++++
> drivers/rpmsg/rpmsg_core.c          |  498 ++++++++++++
> drivers/rpmsg/rpmsg_internal.h      |   82 ++
> drivers/rpmsg/virtio_rpmsg_bus.c    |  487 +++++-------
> include/linux/rpmsg.h               |  246 +-----
> samples/rpmsg/rpmsg_client_sample.c |   14 +-
> 9 files changed, 2266 insertions(+), 517 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
>
>--
>To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" 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] 68+ messages in thread

* [PATCH v2 00/17] Make rpmsg a framework
@ 2016-09-12 16:52   ` Lina Iyer
  0 siblings, 0 replies; 68+ messages in thread
From: Lina Iyer @ 2016-09-12 16:52 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Bjorn,

On Thu, Sep 01 2016 at 16:28 -0600, Bjorn Andersson wrote:
>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.
>

RPM Communication has to supported even when IRQs are disabled. The most
important use of this communication is to set the wake up time for the
CPU subsystem when all the CPUs are powered off. In addition to that,
"sleep" votes that are sent by the application processor subsystem to
allow system to go into deep sleep modes can only be triggered when the
CPU PM domains are power collapsed, drivers do not have a knowledge of
when that happens. This has to be done by a platform code that registers
for CPU PM domain power_off/on callbacks.

Using rpmsg may be nice for RPM SMD communication, but mutexes need to
go away for this driver to be any useful than bare bones active mode
resource requests for QCOM SoCs. By not doing that now, we lock
ourselves out of using this SMD driver in the near future when CPU PM
domains are available in the kernel with an ability to do system low
power modes.

I hope you would make rpmsg work in IRQ disabled contexts first before
porting the SMD driver.

Thanks,
Lina

>
>Changes from v1:
>- Split up the patch moving core code to rpmsg_core into several commits
>- Dropped the wrapping struct in rpmsg_core and just added the ops to the
>  public API (but hid the implementation details)
>- Reordered things to reduce the size of the later patches
>
>Bjorn Andersson (17):
>  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: Make rpmsg_create_ept() take channel_info struct
>  rpmsg: Clean up rpmsg device vs channel naming
>  rpmsg: Introduce indirection table for rpmsg_device operations
>  rpmsg: Move rpmsg_device API to new file
>  rpmsg: Indirection table for rpmsg_endpoint operations
>  rpmsg: Move endpoint related interface to rpmsg core
>  rpmsg: Move helper for finding rpmsg devices to core
>  rpmsg: Split off generic tail of create_channel()
>  rpmsg: Split rpmsg core and virtio backend
>  rpmsg: Hide rpmsg indirection tables
>  rpmsg: virtio: Hide vrp pointer from the public API
>  rpmsg: Move virtio specifics from public header
>  rpmsg: Allow callback to return errors
>  rpmsg: Introduce Qualcomm SMD backend
>
> drivers/remoteproc/Kconfig          |    4 +-
> drivers/rpmsg/Kconfig               |   14 +
> drivers/rpmsg/Makefile              |    4 +-
> drivers/rpmsg/qcom_smd.c            | 1434 +++++++++++++++++++++++++++++++++++
> drivers/rpmsg/rpmsg_core.c          |  498 ++++++++++++
> drivers/rpmsg/rpmsg_internal.h      |   82 ++
> drivers/rpmsg/virtio_rpmsg_bus.c    |  487 +++++-------
> include/linux/rpmsg.h               |  246 +-----
> samples/rpmsg/rpmsg_client_sample.c |   14 +-
> 9 files changed, 2266 insertions(+), 517 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
>
>--
>To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" 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] 68+ messages in thread

* Re: [PATCH v2 00/17] Make rpmsg a framework
  2016-09-12 16:52   ` Lina Iyer
@ 2016-09-12 18:00     ` Bjorn Andersson
  -1 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-12 18:00 UTC (permalink / raw)
  To: Lina Iyer
  Cc: Ohad Ben-Cohen, linux-remoteproc, linux-arm-msm,
	linux-arm-kernel, linux-kernel

On Mon 12 Sep 09:52 PDT 2016, Lina Iyer wrote:

> Hi Bjorn,
> 
> On Thu, Sep 01 2016 at 16:28 -0600, Bjorn Andersson wrote:
> >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.
> >
> 
> RPM Communication has to supported even when IRQs are disabled. The most
> important use of this communication is to set the wake up time for the
> CPU subsystem when all the CPUs are powered off.

Can you point me to the downstream code where this is implemented so I
can have a look? Do you expect to get the response on that request?

> In addition to that,
> "sleep" votes that are sent by the application processor subsystem to
> allow system to go into deep sleep modes can only be triggered when the
> CPU PM domains are power collapsed, drivers do not have a knowledge of
> when that happens.

Do you mean the actual sleep votes can only be with the CPU PM domains
collapsed?

It's been a while since I dug through that code, but there was several
cases where sleep votes would be sent out during normal execution as
well, and then there's the optimization of flushing out all cached sleep
votes when we're on the way down.

> This has to be done by a platform code that registers
> for CPU PM domain power_off/on callbacks.
> 

Ok, sounds like we have a legit use case for improving this.

> Using rpmsg may be nice for RPM SMD communication, but mutexes need to
> go away for this driver to be any useful than bare bones active mode
> resource requests for QCOM SoCs. By not doing that now, we lock
> ourselves out of using this SMD driver in the near future when CPU PM
> domains are available in the kernel with an ability to do system low
> power modes.
> 

The last time I looked at this there where no cases when it was
_required_ to support transmitting requests to the rpm from IRQ context.

iirc we could set up the sleep votes in normal context and the
transition was triggered through SAW(?)

> I hope you would make rpmsg work in IRQ disabled contexts first before
> porting the SMD driver.
> 

There are two parts of this request;

The first is to be able to send data from irq context. The proposed
patches doesn't affect the implementation of send, so it's just a matter
of changing qcom_smd_send() and make the necessary adjustments in the
rpm driver.

In the event of the tx fifo being full we normally do want to sleep on
there being space, but if we switch to spinlocks you would be able to
issue an rpmsg_trysend() which would bypass this - and you can roll a
busy wait in the caller.



The other part is how to receive responses in this mode. Messages are
pulled off the fifo in IRQ context and delivered to the consumer in IRQ
context. But if you have irqs disabled then this wouldn't be triggered.

So if you need your responses we need to figure something out here. And
part of the ugliness of downstream is the need to drain the fifo just
enough before going to sleep, so that the RPM won't stall on a full
fifo.

Regards,
Bjorn

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

* [PATCH v2 00/17] Make rpmsg a framework
@ 2016-09-12 18:00     ` Bjorn Andersson
  0 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-12 18:00 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon 12 Sep 09:52 PDT 2016, Lina Iyer wrote:

> Hi Bjorn,
> 
> On Thu, Sep 01 2016 at 16:28 -0600, Bjorn Andersson wrote:
> >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.
> >
> 
> RPM Communication has to supported even when IRQs are disabled. The most
> important use of this communication is to set the wake up time for the
> CPU subsystem when all the CPUs are powered off.

Can you point me to the downstream code where this is implemented so I
can have a look? Do you expect to get the response on that request?

> In addition to that,
> "sleep" votes that are sent by the application processor subsystem to
> allow system to go into deep sleep modes can only be triggered when the
> CPU PM domains are power collapsed, drivers do not have a knowledge of
> when that happens.

Do you mean the actual sleep votes can only be with the CPU PM domains
collapsed?

It's been a while since I dug through that code, but there was several
cases where sleep votes would be sent out during normal execution as
well, and then there's the optimization of flushing out all cached sleep
votes when we're on the way down.

> This has to be done by a platform code that registers
> for CPU PM domain power_off/on callbacks.
> 

Ok, sounds like we have a legit use case for improving this.

> Using rpmsg may be nice for RPM SMD communication, but mutexes need to
> go away for this driver to be any useful than bare bones active mode
> resource requests for QCOM SoCs. By not doing that now, we lock
> ourselves out of using this SMD driver in the near future when CPU PM
> domains are available in the kernel with an ability to do system low
> power modes.
> 

The last time I looked at this there where no cases when it was
_required_ to support transmitting requests to the rpm from IRQ context.

iirc we could set up the sleep votes in normal context and the
transition was triggered through SAW(?)

> I hope you would make rpmsg work in IRQ disabled contexts first before
> porting the SMD driver.
> 

There are two parts of this request;

The first is to be able to send data from irq context. The proposed
patches doesn't affect the implementation of send, so it's just a matter
of changing qcom_smd_send() and make the necessary adjustments in the
rpm driver.

In the event of the tx fifo being full we normally do want to sleep on
there being space, but if we switch to spinlocks you would be able to
issue an rpmsg_trysend() which would bypass this - and you can roll a
busy wait in the caller.



The other part is how to receive responses in this mode. Messages are
pulled off the fifo in IRQ context and delivered to the consumer in IRQ
context. But if you have irqs disabled then this wouldn't be triggered.

So if you need your responses we need to figure something out here. And
part of the ugliness of downstream is the need to drain the fifo just
enough before going to sleep, so that the RPM won't stall on a full
fifo.

Regards,
Bjorn

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

* Re: [PATCH v2 00/17] Make rpmsg a framework
  2016-09-12 18:00     ` Bjorn Andersson
@ 2016-09-12 18:13       ` Jeffrey Hugo
  -1 siblings, 0 replies; 68+ messages in thread
From: Jeffrey Hugo @ 2016-09-12 18:13 UTC (permalink / raw)
  To: Bjorn Andersson, Lina Iyer
  Cc: Ohad Ben-Cohen, linux-remoteproc, linux-arm-msm,
	linux-arm-kernel, linux-kernel

On 9/12/2016 12:00 PM, Bjorn Andersson wrote:
> On Mon 12 Sep 09:52 PDT 2016, Lina Iyer wrote:
>
>> Hi Bjorn,
>>
>> On Thu, Sep 01 2016 at 16:28 -0600, Bjorn Andersson wrote:
>>> 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.
>>>
>>
>> RPM Communication has to supported even when IRQs are disabled. The most
>> important use of this communication is to set the wake up time for the
>> CPU subsystem when all the CPUs are powered off.
>
> Can you point me to the downstream code where this is implemented so I
> can have a look? Do you expect to get the response on that request?

Have a look at -
smd_mask_receive_interrupt()
smd_is_pkt_avail()

Every request to the RPM generates a response.  The Linux RPM driver may 
decide to let the response sit in the fifo, or it may need to read and 
process it.

>
>> In addition to that,
>> "sleep" votes that are sent by the application processor subsystem to
>> allow system to go into deep sleep modes can only be triggered when the
>> CPU PM domains are power collapsed, drivers do not have a knowledge of
>> when that happens.
>
> Do you mean the actual sleep votes can only be with the CPU PM domains
> collapsed?
>
> It's been a while since I dug through that code, but there was several
> cases where sleep votes would be sent out during normal execution as
> well, and then there's the optimization of flushing out all cached sleep
> votes when we're on the way down.
>
>> This has to be done by a platform code that registers
>> for CPU PM domain power_off/on callbacks.
>>
>
> Ok, sounds like we have a legit use case for improving this.
>
>> Using rpmsg may be nice for RPM SMD communication, but mutexes need to
>> go away for this driver to be any useful than bare bones active mode
>> resource requests for QCOM SoCs. By not doing that now, we lock
>> ourselves out of using this SMD driver in the near future when CPU PM
>> domains are available in the kernel with an ability to do system low
>> power modes.
>>
>
> The last time I looked at this there where no cases when it was
> _required_ to support transmitting requests to the rpm from IRQ context.

I no longer work on SMD, but when I did this was in fact a strict 
requirement.  If I recall correctly, there was a parameter in the RPM 
driver for the transmit function that indicated if the request was being 
made in atomic context or not, which would change the behavior of how 
the transmit was handled.

>
> iirc we could set up the sleep votes in normal context and the
> transition was triggered through SAW(?)
>
>> I hope you would make rpmsg work in IRQ disabled contexts first before
>> porting the SMD driver.
>>
>
> There are two parts of this request;
>
> The first is to be able to send data from irq context. The proposed
> patches doesn't affect the implementation of send, so it's just a matter
> of changing qcom_smd_send() and make the necessary adjustments in the
> rpm driver.
>
> In the event of the tx fifo being full we normally do want to sleep on
> there being space, but if we switch to spinlocks you would be able to
> issue an rpmsg_trysend() which would bypass this - and you can roll a
> busy wait in the caller.
>
>
>
> The other part is how to receive responses in this mode. Messages are
> pulled off the fifo in IRQ context and delivered to the consumer in IRQ
> context. But if you have irqs disabled then this wouldn't be triggered.
>
> So if you need your responses we need to figure something out here. And
> part of the ugliness of downstream is the need to drain the fifo just
> enough before going to sleep, so that the RPM won't stall on a full
> fifo.
>
> Regards,
> Bjorn
> --
> To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Jeffrey Hugo
Qualcomm Datacenter Technologies as an affiliate of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

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

* [PATCH v2 00/17] Make rpmsg a framework
@ 2016-09-12 18:13       ` Jeffrey Hugo
  0 siblings, 0 replies; 68+ messages in thread
From: Jeffrey Hugo @ 2016-09-12 18:13 UTC (permalink / raw)
  To: linux-arm-kernel

On 9/12/2016 12:00 PM, Bjorn Andersson wrote:
> On Mon 12 Sep 09:52 PDT 2016, Lina Iyer wrote:
>
>> Hi Bjorn,
>>
>> On Thu, Sep 01 2016 at 16:28 -0600, Bjorn Andersson wrote:
>>> 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.
>>>
>>
>> RPM Communication has to supported even when IRQs are disabled. The most
>> important use of this communication is to set the wake up time for the
>> CPU subsystem when all the CPUs are powered off.
>
> Can you point me to the downstream code where this is implemented so I
> can have a look? Do you expect to get the response on that request?

Have a look at -
smd_mask_receive_interrupt()
smd_is_pkt_avail()

Every request to the RPM generates a response.  The Linux RPM driver may 
decide to let the response sit in the fifo, or it may need to read and 
process it.

>
>> In addition to that,
>> "sleep" votes that are sent by the application processor subsystem to
>> allow system to go into deep sleep modes can only be triggered when the
>> CPU PM domains are power collapsed, drivers do not have a knowledge of
>> when that happens.
>
> Do you mean the actual sleep votes can only be with the CPU PM domains
> collapsed?
>
> It's been a while since I dug through that code, but there was several
> cases where sleep votes would be sent out during normal execution as
> well, and then there's the optimization of flushing out all cached sleep
> votes when we're on the way down.
>
>> This has to be done by a platform code that registers
>> for CPU PM domain power_off/on callbacks.
>>
>
> Ok, sounds like we have a legit use case for improving this.
>
>> Using rpmsg may be nice for RPM SMD communication, but mutexes need to
>> go away for this driver to be any useful than bare bones active mode
>> resource requests for QCOM SoCs. By not doing that now, we lock
>> ourselves out of using this SMD driver in the near future when CPU PM
>> domains are available in the kernel with an ability to do system low
>> power modes.
>>
>
> The last time I looked at this there where no cases when it was
> _required_ to support transmitting requests to the rpm from IRQ context.

I no longer work on SMD, but when I did this was in fact a strict 
requirement.  If I recall correctly, there was a parameter in the RPM 
driver for the transmit function that indicated if the request was being 
made in atomic context or not, which would change the behavior of how 
the transmit was handled.

>
> iirc we could set up the sleep votes in normal context and the
> transition was triggered through SAW(?)
>
>> I hope you would make rpmsg work in IRQ disabled contexts first before
>> porting the SMD driver.
>>
>
> There are two parts of this request;
>
> The first is to be able to send data from irq context. The proposed
> patches doesn't affect the implementation of send, so it's just a matter
> of changing qcom_smd_send() and make the necessary adjustments in the
> rpm driver.
>
> In the event of the tx fifo being full we normally do want to sleep on
> there being space, but if we switch to spinlocks you would be able to
> issue an rpmsg_trysend() which would bypass this - and you can roll a
> busy wait in the caller.
>
>
>
> The other part is how to receive responses in this mode. Messages are
> pulled off the fifo in IRQ context and delivered to the consumer in IRQ
> context. But if you have irqs disabled then this wouldn't be triggered.
>
> So if you need your responses we need to figure something out here. And
> part of the ugliness of downstream is the need to drain the fifo just
> enough before going to sleep, so that the RPM won't stall on a full
> fifo.
>
> Regards,
> Bjorn
> --
> To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Jeffrey Hugo
Qualcomm Datacenter Technologies as an affiliate of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

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

* Re: [PATCH v2 00/17] Make rpmsg a framework
  2016-09-12 18:13       ` Jeffrey Hugo
@ 2016-09-12 18:49         ` Bjorn Andersson
  -1 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-12 18:49 UTC (permalink / raw)
  To: Jeffrey Hugo
  Cc: Lina Iyer, Ohad Ben-Cohen, linux-remoteproc, linux-arm-msm,
	linux-arm-kernel, linux-kernel

On Mon 12 Sep 11:13 PDT 2016, Jeffrey Hugo wrote:

> On 9/12/2016 12:00 PM, Bjorn Andersson wrote:
> >On Mon 12 Sep 09:52 PDT 2016, Lina Iyer wrote:
> >
> >>Hi Bjorn,
> >>
> >>On Thu, Sep 01 2016 at 16:28 -0600, Bjorn Andersson wrote:
> >>>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.
> >>>
> >>
> >>RPM Communication has to supported even when IRQs are disabled. The most
> >>important use of this communication is to set the wake up time for the
> >>CPU subsystem when all the CPUs are powered off.
> >
> >Can you point me to the downstream code where this is implemented so I
> >can have a look? Do you expect to get the response on that request?
> 
> Have a look at -
> smd_mask_receive_interrupt()
> smd_is_pkt_avail()
> 

In msm-3.18 these still seems to only come from either
msm_rpm_enter_sleep() and the rpm-clock driver, related to flushing
cached sleep state requests.

> Every request to the RPM generates a response.  The Linux RPM driver may
> decide to let the response sit in the fifo, or it may need to read and
> process it.
> 

Right, I presume we save some time by not waiting for these responses as
we want to reach sleep as soon as possible. The answer I got last time
this was discussed was that it was an optimization, not a functional
requirement.


I'm not at all against having the rpm driver cache the state
information and the smd driver process read/writes from the rpm driver
in IRQ context. I do however not know how to trigger the flush in a sane
way.

> >
> >>In addition to that,
> >>"sleep" votes that are sent by the application processor subsystem to
> >>allow system to go into deep sleep modes can only be triggered when the
> >>CPU PM domains are power collapsed, drivers do not have a knowledge of
> >>when that happens.
> >
> >Do you mean the actual sleep votes can only be with the CPU PM domains
> >collapsed?
> >
> >It's been a while since I dug through that code, but there was several
> >cases where sleep votes would be sent out during normal execution as
> >well, and then there's the optimization of flushing out all cached sleep
> >votes when we're on the way down.
> >
> >>This has to be done by a platform code that registers
> >>for CPU PM domain power_off/on callbacks.
> >>
> >
> >Ok, sounds like we have a legit use case for improving this.
> >
> >>Using rpmsg may be nice for RPM SMD communication, but mutexes need to
> >>go away for this driver to be any useful than bare bones active mode
> >>resource requests for QCOM SoCs. By not doing that now, we lock
> >>ourselves out of using this SMD driver in the near future when CPU PM
> >>domains are available in the kernel with an ability to do system low
> >>power modes.
> >>
> >
> >The last time I looked at this there where no cases when it was
> >_required_ to support transmitting requests to the rpm from IRQ context.
> 
> I no longer work on SMD, but when I did this was in fact a strict
> requirement.

When I dissected all the users of the API I came to the conclusion that
this requirement (on the SMD driver) came from above mentioned
optimization.

> If I recall correctly, there was a parameter in the RPM driver
> for the transmit function that indicated if the request was being made in
> atomic context or not, which would change the behavior of how the transmit
> was handled.
> 

You're correct, the question is still which of these code paths are
actually needed and to motivate the endless maintenance of the extra
code.


Nice to see you on the mailing list again Jeff.

Regards,
Bjorn

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

* [PATCH v2 00/17] Make rpmsg a framework
@ 2016-09-12 18:49         ` Bjorn Andersson
  0 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-12 18:49 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon 12 Sep 11:13 PDT 2016, Jeffrey Hugo wrote:

> On 9/12/2016 12:00 PM, Bjorn Andersson wrote:
> >On Mon 12 Sep 09:52 PDT 2016, Lina Iyer wrote:
> >
> >>Hi Bjorn,
> >>
> >>On Thu, Sep 01 2016 at 16:28 -0600, Bjorn Andersson wrote:
> >>>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.
> >>>
> >>
> >>RPM Communication has to supported even when IRQs are disabled. The most
> >>important use of this communication is to set the wake up time for the
> >>CPU subsystem when all the CPUs are powered off.
> >
> >Can you point me to the downstream code where this is implemented so I
> >can have a look? Do you expect to get the response on that request?
> 
> Have a look at -
> smd_mask_receive_interrupt()
> smd_is_pkt_avail()
> 

In msm-3.18 these still seems to only come from either
msm_rpm_enter_sleep() and the rpm-clock driver, related to flushing
cached sleep state requests.

> Every request to the RPM generates a response.  The Linux RPM driver may
> decide to let the response sit in the fifo, or it may need to read and
> process it.
> 

Right, I presume we save some time by not waiting for these responses as
we want to reach sleep as soon as possible. The answer I got last time
this was discussed was that it was an optimization, not a functional
requirement.


I'm not at all against having the rpm driver cache the state
information and the smd driver process read/writes from the rpm driver
in IRQ context. I do however not know how to trigger the flush in a sane
way.

> >
> >>In addition to that,
> >>"sleep" votes that are sent by the application processor subsystem to
> >>allow system to go into deep sleep modes can only be triggered when the
> >>CPU PM domains are power collapsed, drivers do not have a knowledge of
> >>when that happens.
> >
> >Do you mean the actual sleep votes can only be with the CPU PM domains
> >collapsed?
> >
> >It's been a while since I dug through that code, but there was several
> >cases where sleep votes would be sent out during normal execution as
> >well, and then there's the optimization of flushing out all cached sleep
> >votes when we're on the way down.
> >
> >>This has to be done by a platform code that registers
> >>for CPU PM domain power_off/on callbacks.
> >>
> >
> >Ok, sounds like we have a legit use case for improving this.
> >
> >>Using rpmsg may be nice for RPM SMD communication, but mutexes need to
> >>go away for this driver to be any useful than bare bones active mode
> >>resource requests for QCOM SoCs. By not doing that now, we lock
> >>ourselves out of using this SMD driver in the near future when CPU PM
> >>domains are available in the kernel with an ability to do system low
> >>power modes.
> >>
> >
> >The last time I looked at this there where no cases when it was
> >_required_ to support transmitting requests to the rpm from IRQ context.
> 
> I no longer work on SMD, but when I did this was in fact a strict
> requirement.

When I dissected all the users of the API I came to the conclusion that
this requirement (on the SMD driver) came from above mentioned
optimization.

> If I recall correctly, there was a parameter in the RPM driver
> for the transmit function that indicated if the request was being made in
> atomic context or not, which would change the behavior of how the transmit
> was handled.
> 

You're correct, the question is still which of these code paths are
actually needed and to motivate the endless maintenance of the extra
code.


Nice to see you on the mailing list again Jeff.

Regards,
Bjorn

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

* Re: [PATCH v2 00/17] Make rpmsg a framework
  2016-09-12 18:49         ` Bjorn Andersson
@ 2016-09-12 19:21           ` Jeffrey Hugo
  -1 siblings, 0 replies; 68+ messages in thread
From: Jeffrey Hugo @ 2016-09-12 19:21 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Lina Iyer, Ohad Ben-Cohen, linux-remoteproc, linux-arm-msm,
	linux-arm-kernel, linux-kernel

On 9/12/2016 12:49 PM, Bjorn Andersson wrote:
> On Mon 12 Sep 11:13 PDT 2016, Jeffrey Hugo wrote:
>
>> On 9/12/2016 12:00 PM, Bjorn Andersson wrote:
>>> On Mon 12 Sep 09:52 PDT 2016, Lina Iyer wrote:
>>>
>>>> Hi Bjorn,
>>>>
>>>> On Thu, Sep 01 2016 at 16:28 -0600, Bjorn Andersson wrote:
>>>>> 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.
>>>>>
>>>>
>>>> RPM Communication has to supported even when IRQs are disabled. The most
>>>> important use of this communication is to set the wake up time for the
>>>> CPU subsystem when all the CPUs are powered off.
>>>
>>> Can you point me to the downstream code where this is implemented so I
>>> can have a look? Do you expect to get the response on that request?
>>
>> Have a look at -
>> smd_mask_receive_interrupt()
>> smd_is_pkt_avail()
>>
>
> In msm-3.18 these still seems to only come from either
> msm_rpm_enter_sleep() and the rpm-clock driver, related to flushing
> cached sleep state requests.
>
>> Every request to the RPM generates a response.  The Linux RPM driver may
>> decide to let the response sit in the fifo, or it may need to read and
>> process it.
>>
>
> Right, I presume we save some time by not waiting for these responses as
> we want to reach sleep as soon as possible. The answer I got last time
> this was discussed was that it was an optimization, not a functional
> requirement.

Two optimizations in play here.

First, disabling interrupts prevents an immediate wakeup.  When the 
system is entering sleep, IRQs are disabled.  The sleep request to RPM 
will trigger a response, and the IRQ for that response will be queued. 
Once the sleep processing is done, IRQs get enabled, so the pending IRQ 
from RPM will cause an immediate wakeup.  The system will process the 
wakeup, and then go back to sleep (sans request because nothing has 
changed).  This down-up-down processing burns a lot of power.

Second is not waiting for the response.  Linux doesn't really do 
anything with the sleep request response, so we can enter sleep faster 
by not waiting for the response and processing (discarding) it when the 
system wakes up as scheduled.  However, Linux needs to ensure there is 
enough fifo space to hold that response while asleep, otherwise the RPM 
will panic and crash the system.  Therefore, if there are a number of 
outstanding requests that would fill the fifo, then the RPM driver on 
Linux needs to spin and drain requests from the fifo until a minimum 
free space buffer to hold additional expected pending responses is 
established.  This has to occur with IRQs disabled.

>
>
> I'm not at all against having the rpm driver cache the state
> information and the smd driver process read/writes from the rpm driver
> in IRQ context. I do however not know how to trigger the flush in a sane
> way.
>
>>>
>>>> In addition to that,
>>>> "sleep" votes that are sent by the application processor subsystem to
>>>> allow system to go into deep sleep modes can only be triggered when the
>>>> CPU PM domains are power collapsed, drivers do not have a knowledge of
>>>> when that happens.
>>>
>>> Do you mean the actual sleep votes can only be with the CPU PM domains
>>> collapsed?
>>>
>>> It's been a while since I dug through that code, but there was several
>>> cases where sleep votes would be sent out during normal execution as
>>> well, and then there's the optimization of flushing out all cached sleep
>>> votes when we're on the way down.
>>>
>>>> This has to be done by a platform code that registers
>>>> for CPU PM domain power_off/on callbacks.
>>>>
>>>
>>> Ok, sounds like we have a legit use case for improving this.
>>>
>>>> Using rpmsg may be nice for RPM SMD communication, but mutexes need to
>>>> go away for this driver to be any useful than bare bones active mode
>>>> resource requests for QCOM SoCs. By not doing that now, we lock
>>>> ourselves out of using this SMD driver in the near future when CPU PM
>>>> domains are available in the kernel with an ability to do system low
>>>> power modes.
>>>>
>>>
>>> The last time I looked at this there where no cases when it was
>>> _required_ to support transmitting requests to the rpm from IRQ context.
>>
>> I no longer work on SMD, but when I did this was in fact a strict
>> requirement.
>
> When I dissected all the users of the API I came to the conclusion that
> this requirement (on the SMD driver) came from above mentioned
> optimization.
>
>> If I recall correctly, there was a parameter in the RPM driver
>> for the transmit function that indicated if the request was being made in
>> atomic context or not, which would change the behavior of how the transmit
>> was handled.
>>
>
> You're correct, the question is still which of these code paths are
> actually needed and to motivate the endless maintenance of the extra
> code.

If we are just talking about transmitting in atomic context (not 
necessarily related to sleep), if I recall correctly, some bus requests 
are sent to RPM in atomic context, some APR requests to the Audio DSP 
are done in atomic context, and I think IPC Router uses atomic context 
in some cases.  As a generic framework that should support usecases to 
all processors/subsystems, I don't think transmitting in atomic context 
is a special case for RPM/sleep.

Lina et al would probably know better about the usecase details than I 
at this point however.

>
>
> Nice to see you on the mailing list again Jeff.
>
> Regards,
> Bjorn
>


-- 
Jeffrey Hugo
Qualcomm Datacenter Technologies as an affiliate of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

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

* [PATCH v2 00/17] Make rpmsg a framework
@ 2016-09-12 19:21           ` Jeffrey Hugo
  0 siblings, 0 replies; 68+ messages in thread
From: Jeffrey Hugo @ 2016-09-12 19:21 UTC (permalink / raw)
  To: linux-arm-kernel

On 9/12/2016 12:49 PM, Bjorn Andersson wrote:
> On Mon 12 Sep 11:13 PDT 2016, Jeffrey Hugo wrote:
>
>> On 9/12/2016 12:00 PM, Bjorn Andersson wrote:
>>> On Mon 12 Sep 09:52 PDT 2016, Lina Iyer wrote:
>>>
>>>> Hi Bjorn,
>>>>
>>>> On Thu, Sep 01 2016 at 16:28 -0600, Bjorn Andersson wrote:
>>>>> 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.
>>>>>
>>>>
>>>> RPM Communication has to supported even when IRQs are disabled. The most
>>>> important use of this communication is to set the wake up time for the
>>>> CPU subsystem when all the CPUs are powered off.
>>>
>>> Can you point me to the downstream code where this is implemented so I
>>> can have a look? Do you expect to get the response on that request?
>>
>> Have a look at -
>> smd_mask_receive_interrupt()
>> smd_is_pkt_avail()
>>
>
> In msm-3.18 these still seems to only come from either
> msm_rpm_enter_sleep() and the rpm-clock driver, related to flushing
> cached sleep state requests.
>
>> Every request to the RPM generates a response.  The Linux RPM driver may
>> decide to let the response sit in the fifo, or it may need to read and
>> process it.
>>
>
> Right, I presume we save some time by not waiting for these responses as
> we want to reach sleep as soon as possible. The answer I got last time
> this was discussed was that it was an optimization, not a functional
> requirement.

Two optimizations in play here.

First, disabling interrupts prevents an immediate wakeup.  When the 
system is entering sleep, IRQs are disabled.  The sleep request to RPM 
will trigger a response, and the IRQ for that response will be queued. 
Once the sleep processing is done, IRQs get enabled, so the pending IRQ 
from RPM will cause an immediate wakeup.  The system will process the 
wakeup, and then go back to sleep (sans request because nothing has 
changed).  This down-up-down processing burns a lot of power.

Second is not waiting for the response.  Linux doesn't really do 
anything with the sleep request response, so we can enter sleep faster 
by not waiting for the response and processing (discarding) it when the 
system wakes up as scheduled.  However, Linux needs to ensure there is 
enough fifo space to hold that response while asleep, otherwise the RPM 
will panic and crash the system.  Therefore, if there are a number of 
outstanding requests that would fill the fifo, then the RPM driver on 
Linux needs to spin and drain requests from the fifo until a minimum 
free space buffer to hold additional expected pending responses is 
established.  This has to occur with IRQs disabled.

>
>
> I'm not at all against having the rpm driver cache the state
> information and the smd driver process read/writes from the rpm driver
> in IRQ context. I do however not know how to trigger the flush in a sane
> way.
>
>>>
>>>> In addition to that,
>>>> "sleep" votes that are sent by the application processor subsystem to
>>>> allow system to go into deep sleep modes can only be triggered when the
>>>> CPU PM domains are power collapsed, drivers do not have a knowledge of
>>>> when that happens.
>>>
>>> Do you mean the actual sleep votes can only be with the CPU PM domains
>>> collapsed?
>>>
>>> It's been a while since I dug through that code, but there was several
>>> cases where sleep votes would be sent out during normal execution as
>>> well, and then there's the optimization of flushing out all cached sleep
>>> votes when we're on the way down.
>>>
>>>> This has to be done by a platform code that registers
>>>> for CPU PM domain power_off/on callbacks.
>>>>
>>>
>>> Ok, sounds like we have a legit use case for improving this.
>>>
>>>> Using rpmsg may be nice for RPM SMD communication, but mutexes need to
>>>> go away for this driver to be any useful than bare bones active mode
>>>> resource requests for QCOM SoCs. By not doing that now, we lock
>>>> ourselves out of using this SMD driver in the near future when CPU PM
>>>> domains are available in the kernel with an ability to do system low
>>>> power modes.
>>>>
>>>
>>> The last time I looked at this there where no cases when it was
>>> _required_ to support transmitting requests to the rpm from IRQ context.
>>
>> I no longer work on SMD, but when I did this was in fact a strict
>> requirement.
>
> When I dissected all the users of the API I came to the conclusion that
> this requirement (on the SMD driver) came from above mentioned
> optimization.
>
>> If I recall correctly, there was a parameter in the RPM driver
>> for the transmit function that indicated if the request was being made in
>> atomic context or not, which would change the behavior of how the transmit
>> was handled.
>>
>
> You're correct, the question is still which of these code paths are
> actually needed and to motivate the endless maintenance of the extra
> code.

If we are just talking about transmitting in atomic context (not 
necessarily related to sleep), if I recall correctly, some bus requests 
are sent to RPM in atomic context, some APR requests to the Audio DSP 
are done in atomic context, and I think IPC Router uses atomic context 
in some cases.  As a generic framework that should support usecases to 
all processors/subsystems, I don't think transmitting in atomic context 
is a special case for RPM/sleep.

Lina et al would probably know better about the usecase details than I 
at this point however.

>
>
> Nice to see you on the mailing list again Jeff.
>
> Regards,
> Bjorn
>


-- 
Jeffrey Hugo
Qualcomm Datacenter Technologies as an affiliate of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

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

* Re: [PATCH v2 00/17] Make rpmsg a framework
  2016-09-12 19:21           ` Jeffrey Hugo
@ 2016-09-12 19:58             ` Bjorn Andersson
  -1 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-12 19:58 UTC (permalink / raw)
  To: Jeffrey Hugo
  Cc: Lina Iyer, Ohad Ben-Cohen, linux-remoteproc, linux-arm-msm,
	linux-arm-kernel, linux-kernel

On Mon 12 Sep 12:21 PDT 2016, Jeffrey Hugo wrote:

> On 9/12/2016 12:49 PM, Bjorn Andersson wrote:
> >On Mon 12 Sep 11:13 PDT 2016, Jeffrey Hugo wrote:
> >
> >>On 9/12/2016 12:00 PM, Bjorn Andersson wrote:
[..]
> >>>Can you point me to the downstream code where this is implemented so I
> >>>can have a look? Do you expect to get the response on that request?
> >>
> >>Have a look at -
> >>smd_mask_receive_interrupt()
> >>smd_is_pkt_avail()
> >>
> >
> >In msm-3.18 these still seems to only come from either
> >msm_rpm_enter_sleep() and the rpm-clock driver, related to flushing
> >cached sleep state requests.
> >
> >>Every request to the RPM generates a response.  The Linux RPM driver may
> >>decide to let the response sit in the fifo, or it may need to read and
> >>process it.
> >>
> >
> >Right, I presume we save some time by not waiting for these responses as
> >we want to reach sleep as soon as possible. The answer I got last time
> >this was discussed was that it was an optimization, not a functional
> >requirement.
> 
> Two optimizations in play here.
> 
> First, disabling interrupts prevents an immediate wakeup.  When the system
> is entering sleep, IRQs are disabled.  The sleep request to RPM will trigger
> a response, and the IRQ for that response will be queued. Once the sleep
> processing is done, IRQs get enabled, so the pending IRQ from RPM will cause
> an immediate wakeup.  The system will process the wakeup, and then go back
> to sleep (sans request because nothing has changed).  This down-up-down
> processing burns a lot of power.
> 

But which "sleep request" is this? The only one I can find is the
flushing of sleep state values from the rpm resource tables.

> Second is not waiting for the response.  Linux doesn't really do anything
> with the sleep request response, so we can enter sleep faster by not waiting
> for the response and processing (discarding) it when the system wakes up as
> scheduled.

Right, as long as the RPM code doesn't consider it a timeout don't have
a problem if those ack's are handled after the resume.

> However, Linux needs to ensure there is enough fifo space to
> hold that response while asleep, otherwise the RPM will panic and crash the
> system.  Therefore, if there are a number of outstanding requests that would
> fill the fifo, then the RPM driver on Linux needs to spin and drain requests
> from the fifo until a minimum free space buffer to hold additional expected
> pending responses is established.  This has to occur with IRQs disabled.
> 

Right. Which means that the RPM driver needs to know how large the rx
fifo is, what overhead the underlaying transport mechanism has and then
calculate how many responses it should leave room for.

[..]
> >>If I recall correctly, there was a parameter in the RPM driver
> >>for the transmit function that indicated if the request was being made in
> >>atomic context or not, which would change the behavior of how the transmit
> >>was handled.
> >>
> >
> >You're correct, the question is still which of these code paths are
> >actually needed and to motivate the endless maintenance of the extra
> >code.
> 
> If we are just talking about transmitting in atomic context (not necessarily
> related to sleep), if I recall correctly, some bus requests are sent to RPM
> in atomic context, some APR requests to the Audio DSP are done in atomic
> context, and I think IPC Router uses atomic context in some cases.  As a
> generic framework that should support usecases to all processors/subsystems,
> I don't think transmitting in atomic context is a special case for
> RPM/sleep.
> 

I have not looked through all of APR yet and don't know where msm_bus is
heading, but for IPC-router your correct that the downstream driver does
indeed require this; but that's a side effect of the downstream
ipcrouter implementation, not the problem itself.

Regards,
Bjorn

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

* [PATCH v2 00/17] Make rpmsg a framework
@ 2016-09-12 19:58             ` Bjorn Andersson
  0 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-12 19:58 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon 12 Sep 12:21 PDT 2016, Jeffrey Hugo wrote:

> On 9/12/2016 12:49 PM, Bjorn Andersson wrote:
> >On Mon 12 Sep 11:13 PDT 2016, Jeffrey Hugo wrote:
> >
> >>On 9/12/2016 12:00 PM, Bjorn Andersson wrote:
[..]
> >>>Can you point me to the downstream code where this is implemented so I
> >>>can have a look? Do you expect to get the response on that request?
> >>
> >>Have a look at -
> >>smd_mask_receive_interrupt()
> >>smd_is_pkt_avail()
> >>
> >
> >In msm-3.18 these still seems to only come from either
> >msm_rpm_enter_sleep() and the rpm-clock driver, related to flushing
> >cached sleep state requests.
> >
> >>Every request to the RPM generates a response.  The Linux RPM driver may
> >>decide to let the response sit in the fifo, or it may need to read and
> >>process it.
> >>
> >
> >Right, I presume we save some time by not waiting for these responses as
> >we want to reach sleep as soon as possible. The answer I got last time
> >this was discussed was that it was an optimization, not a functional
> >requirement.
> 
> Two optimizations in play here.
> 
> First, disabling interrupts prevents an immediate wakeup.  When the system
> is entering sleep, IRQs are disabled.  The sleep request to RPM will trigger
> a response, and the IRQ for that response will be queued. Once the sleep
> processing is done, IRQs get enabled, so the pending IRQ from RPM will cause
> an immediate wakeup.  The system will process the wakeup, and then go back
> to sleep (sans request because nothing has changed).  This down-up-down
> processing burns a lot of power.
> 

But which "sleep request" is this? The only one I can find is the
flushing of sleep state values from the rpm resource tables.

> Second is not waiting for the response.  Linux doesn't really do anything
> with the sleep request response, so we can enter sleep faster by not waiting
> for the response and processing (discarding) it when the system wakes up as
> scheduled.

Right, as long as the RPM code doesn't consider it a timeout don't have
a problem if those ack's are handled after the resume.

> However, Linux needs to ensure there is enough fifo space to
> hold that response while asleep, otherwise the RPM will panic and crash the
> system.  Therefore, if there are a number of outstanding requests that would
> fill the fifo, then the RPM driver on Linux needs to spin and drain requests
> from the fifo until a minimum free space buffer to hold additional expected
> pending responses is established.  This has to occur with IRQs disabled.
> 

Right. Which means that the RPM driver needs to know how large the rx
fifo is, what overhead the underlaying transport mechanism has and then
calculate how many responses it should leave room for.

[..]
> >>If I recall correctly, there was a parameter in the RPM driver
> >>for the transmit function that indicated if the request was being made in
> >>atomic context or not, which would change the behavior of how the transmit
> >>was handled.
> >>
> >
> >You're correct, the question is still which of these code paths are
> >actually needed and to motivate the endless maintenance of the extra
> >code.
> 
> If we are just talking about transmitting in atomic context (not necessarily
> related to sleep), if I recall correctly, some bus requests are sent to RPM
> in atomic context, some APR requests to the Audio DSP are done in atomic
> context, and I think IPC Router uses atomic context in some cases.  As a
> generic framework that should support usecases to all processors/subsystems,
> I don't think transmitting in atomic context is a special case for
> RPM/sleep.
> 

I have not looked through all of APR yet and don't know where msm_bus is
heading, but for IPC-router your correct that the downstream driver does
indeed require this; but that's a side effect of the downstream
ipcrouter implementation, not the problem itself.

Regards,
Bjorn

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

* Re: [PATCH v2 00/17] Make rpmsg a framework
  2016-09-12 19:58             ` Bjorn Andersson
@ 2016-09-12 21:36               ` Karthikeyan Ramasubramanian
  -1 siblings, 0 replies; 68+ messages in thread
From: Karthikeyan Ramasubramanian @ 2016-09-12 21:36 UTC (permalink / raw)
  To: Bjorn Andersson, Jeffrey Hugo
  Cc: Lina Iyer, Ohad Ben-Cohen, linux-remoteproc, linux-arm-msm,
	linux-arm-kernel, linux-kernel

On 9/12/2016 1:58 PM, Bjorn Andersson wrote:
> On Mon 12 Sep 12:21 PDT 2016, Jeffrey Hugo wrote:
>
>> On 9/12/2016 12:49 PM, Bjorn Andersson wrote:
>>> On Mon 12 Sep 11:13 PDT 2016, Jeffrey Hugo wrote:
>>>
>>>> On 9/12/2016 12:00 PM, Bjorn Andersson wrote:
> [..]
>>>>> Can you point me to the downstream code where this is implemented so I
>>>>> can have a look? Do you expect to get the response on that request?
>>>>
>>>> Have a look at -
>>>> smd_mask_receive_interrupt()
>>>> smd_is_pkt_avail()
>>>>
>>>
>>> In msm-3.18 these still seems to only come from either
>>> msm_rpm_enter_sleep() and the rpm-clock driver, related to flushing
>>> cached sleep state requests.
>>>
>>>> Every request to the RPM generates a response.  The Linux RPM driver may
>>>> decide to let the response sit in the fifo, or it may need to read and
>>>> process it.
>>>>
>>>
>>> Right, I presume we save some time by not waiting for these responses as
>>> we want to reach sleep as soon as possible. The answer I got last time
>>> this was discussed was that it was an optimization, not a functional
>>> requirement.
>>
>> Two optimizations in play here.
>>
>> First, disabling interrupts prevents an immediate wakeup.  When the system
>> is entering sleep, IRQs are disabled.  The sleep request to RPM will trigger
>> a response, and the IRQ for that response will be queued. Once the sleep
>> processing is done, IRQs get enabled, so the pending IRQ from RPM will cause
>> an immediate wakeup.  The system will process the wakeup, and then go back
>> to sleep (sans request because nothing has changed).  This down-up-down
>> processing burns a lot of power.
>>
>
> But which "sleep request" is this? The only one I can find is the
> flushing of sleep state values from the rpm resource tables.
>
>> Second is not waiting for the response.  Linux doesn't really do anything
>> with the sleep request response, so we can enter sleep faster by not waiting
>> for the response and processing (discarding) it when the system wakes up as
>> scheduled.
>
> Right, as long as the RPM code doesn't consider it a timeout don't have
> a problem if those ack's are handled after the resume.
>
>> However, Linux needs to ensure there is enough fifo space to
>> hold that response while asleep, otherwise the RPM will panic and crash the
>> system.  Therefore, if there are a number of outstanding requests that would
>> fill the fifo, then the RPM driver on Linux needs to spin and drain requests
>> from the fifo until a minimum free space buffer to hold additional expected
>> pending responses is established.  This has to occur with IRQs disabled.
>>
>
> Right. Which means that the RPM driver needs to know how large the rx
> fifo is, what overhead the underlaying transport mechanism has and then
> calculate how many responses it should leave room for.
>
> [..]
>>>> If I recall correctly, there was a parameter in the RPM driver
>>>> for the transmit function that indicated if the request was being made in
>>>> atomic context or not, which would change the behavior of how the transmit
>>>> was handled.
>>>>
>>>
>>> You're correct, the question is still which of these code paths are
>>> actually needed and to motivate the endless maintenance of the extra
>>> code.
>>
>> If we are just talking about transmitting in atomic context (not necessarily
>> related to sleep), if I recall correctly, some bus requests are sent to RPM
>> in atomic context, some APR requests to the Audio DSP are done in atomic
>> context, and I think IPC Router uses atomic context in some cases.  As a
>> generic framework that should support usecases to all processors/subsystems,
>> I don't think transmitting in atomic context is a special case for
>> RPM/sleep.
>>
>
> I have not looked through all of APR yet and don't know where msm_bus is
> heading, but for IPC-router your correct that the downstream driver does
> indeed require this; but that's a side effect of the downstream
> ipcrouter implementation, not the problem itself.
>
APR does send messages in atomic context in addition to the RPM Driver, 
but IPC Router does not to the extent of my knowledge.
> Regards,
> Bjorn
> --
> To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

Regards,
Karthik.
-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
  hosted by The Linux Foundation

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

* [PATCH v2 00/17] Make rpmsg a framework
@ 2016-09-12 21:36               ` Karthikeyan Ramasubramanian
  0 siblings, 0 replies; 68+ messages in thread
From: Karthikeyan Ramasubramanian @ 2016-09-12 21:36 UTC (permalink / raw)
  To: linux-arm-kernel

On 9/12/2016 1:58 PM, Bjorn Andersson wrote:
> On Mon 12 Sep 12:21 PDT 2016, Jeffrey Hugo wrote:
>
>> On 9/12/2016 12:49 PM, Bjorn Andersson wrote:
>>> On Mon 12 Sep 11:13 PDT 2016, Jeffrey Hugo wrote:
>>>
>>>> On 9/12/2016 12:00 PM, Bjorn Andersson wrote:
> [..]
>>>>> Can you point me to the downstream code where this is implemented so I
>>>>> can have a look? Do you expect to get the response on that request?
>>>>
>>>> Have a look at -
>>>> smd_mask_receive_interrupt()
>>>> smd_is_pkt_avail()
>>>>
>>>
>>> In msm-3.18 these still seems to only come from either
>>> msm_rpm_enter_sleep() and the rpm-clock driver, related to flushing
>>> cached sleep state requests.
>>>
>>>> Every request to the RPM generates a response.  The Linux RPM driver may
>>>> decide to let the response sit in the fifo, or it may need to read and
>>>> process it.
>>>>
>>>
>>> Right, I presume we save some time by not waiting for these responses as
>>> we want to reach sleep as soon as possible. The answer I got last time
>>> this was discussed was that it was an optimization, not a functional
>>> requirement.
>>
>> Two optimizations in play here.
>>
>> First, disabling interrupts prevents an immediate wakeup.  When the system
>> is entering sleep, IRQs are disabled.  The sleep request to RPM will trigger
>> a response, and the IRQ for that response will be queued. Once the sleep
>> processing is done, IRQs get enabled, so the pending IRQ from RPM will cause
>> an immediate wakeup.  The system will process the wakeup, and then go back
>> to sleep (sans request because nothing has changed).  This down-up-down
>> processing burns a lot of power.
>>
>
> But which "sleep request" is this? The only one I can find is the
> flushing of sleep state values from the rpm resource tables.
>
>> Second is not waiting for the response.  Linux doesn't really do anything
>> with the sleep request response, so we can enter sleep faster by not waiting
>> for the response and processing (discarding) it when the system wakes up as
>> scheduled.
>
> Right, as long as the RPM code doesn't consider it a timeout don't have
> a problem if those ack's are handled after the resume.
>
>> However, Linux needs to ensure there is enough fifo space to
>> hold that response while asleep, otherwise the RPM will panic and crash the
>> system.  Therefore, if there are a number of outstanding requests that would
>> fill the fifo, then the RPM driver on Linux needs to spin and drain requests
>> from the fifo until a minimum free space buffer to hold additional expected
>> pending responses is established.  This has to occur with IRQs disabled.
>>
>
> Right. Which means that the RPM driver needs to know how large the rx
> fifo is, what overhead the underlaying transport mechanism has and then
> calculate how many responses it should leave room for.
>
> [..]
>>>> If I recall correctly, there was a parameter in the RPM driver
>>>> for the transmit function that indicated if the request was being made in
>>>> atomic context or not, which would change the behavior of how the transmit
>>>> was handled.
>>>>
>>>
>>> You're correct, the question is still which of these code paths are
>>> actually needed and to motivate the endless maintenance of the extra
>>> code.
>>
>> If we are just talking about transmitting in atomic context (not necessarily
>> related to sleep), if I recall correctly, some bus requests are sent to RPM
>> in atomic context, some APR requests to the Audio DSP are done in atomic
>> context, and I think IPC Router uses atomic context in some cases.  As a
>> generic framework that should support usecases to all processors/subsystems,
>> I don't think transmitting in atomic context is a special case for
>> RPM/sleep.
>>
>
> I have not looked through all of APR yet and don't know where msm_bus is
> heading, but for IPC-router your correct that the downstream driver does
> indeed require this; but that's a side effect of the downstream
> ipcrouter implementation, not the problem itself.
>
APR does send messages in atomic context in addition to the RPM Driver, 
but IPC Router does not to the extent of my knowledge.
> Regards,
> Bjorn
> --
> To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

Regards,
Karthik.
-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
  hosted by The Linux Foundation

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

* Re: [PATCH v2 00/17] Make rpmsg a framework
  2016-09-12 21:36               ` Karthikeyan Ramasubramanian
@ 2016-09-12 21:53                 ` Bjorn Andersson
  -1 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-12 21:53 UTC (permalink / raw)
  To: Karthikeyan Ramasubramanian
  Cc: Jeffrey Hugo, Lina Iyer, Ohad Ben-Cohen, linux-remoteproc,
	linux-arm-msm, linux-arm-kernel, linux-kernel

On Mon 12 Sep 14:36 PDT 2016, Karthikeyan Ramasubramanian wrote:

> On 9/12/2016 1:58 PM, Bjorn Andersson wrote:
[..]
> >I have not looked through all of APR yet and don't know where msm_bus is
> >heading, but for IPC-router your correct that the downstream driver does
> >indeed require this; but that's a side effect of the downstream
> >ipcrouter implementation, not the problem itself.
> >
> APR does send messages in atomic context in addition to the RPM Driver, but
> IPC Router does not to the extent of my knowledge.

Thanks for the information, Karthik.

There seem to be 196 calls to apr_send_pkt() in the msm-3.18 kernel, I
will have to go through them all later, but could you help me by
pointing me to one of those that actually need to be executed in atomic
context?

Thanks,
Bjorn

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

* [PATCH v2 00/17] Make rpmsg a framework
@ 2016-09-12 21:53                 ` Bjorn Andersson
  0 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-12 21:53 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon 12 Sep 14:36 PDT 2016, Karthikeyan Ramasubramanian wrote:

> On 9/12/2016 1:58 PM, Bjorn Andersson wrote:
[..]
> >I have not looked through all of APR yet and don't know where msm_bus is
> >heading, but for IPC-router your correct that the downstream driver does
> >indeed require this; but that's a side effect of the downstream
> >ipcrouter implementation, not the problem itself.
> >
> APR does send messages in atomic context in addition to the RPM Driver, but
> IPC Router does not to the extent of my knowledge.

Thanks for the information, Karthik.

There seem to be 196 calls to apr_send_pkt() in the msm-3.18 kernel, I
will have to go through them all later, but could you help me by
pointing me to one of those that actually need to be executed in atomic
context?

Thanks,
Bjorn

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

* Re: [PATCH v2 00/17] Make rpmsg a framework
  2016-09-12 16:52   ` Lina Iyer
@ 2016-09-12 22:22     ` Lina Iyer
  -1 siblings, 0 replies; 68+ messages in thread
From: Lina Iyer @ 2016-09-12 22:22 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Ohad Ben-Cohen, linux-remoteproc, linux-arm-msm,
	linux-arm-kernel, linux-kernel

On Mon, Sep 12 2016 at 10:52 -0600, Lina Iyer wrote:
>Hi Bjorn,
>
>On Thu, Sep 01 2016 at 16:28 -0600, Bjorn Andersson wrote:
>>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.
>>
>
>RPM Communication has to supported even when IRQs are disabled. The most
>important use of this communication is to set the wake up time for the
>CPU subsystem when all the CPUs are powered off. In addition to that,
>"sleep" votes that are sent by the application processor subsystem to
>allow system to go into deep sleep modes can only be triggered when the
>CPU PM domains are power collapsed, drivers do not have a knowledge of
>when that happens. This has to be done by a platform code that registers
>for CPU PM domain power_off/on callbacks.
>
Ok, my bad. These two cases are not critical for the SoC supported by
this driver. So you are good to go from cpuidle perspective

>Using rpmsg may be nice for RPM SMD communication, but mutexes need to
>go away for this driver to be any useful than bare bones active mode
>resource requests for QCOM SoCs. By not doing that now, we lock
>ourselves out of using this SMD driver in the near future when CPU PM
>domains are available in the kernel with an ability to do system low
>power modes.
>
>I hope you would make rpmsg work in IRQ disabled contexts first before
>porting the SMD driver.
>
>Thanks,
>Lina
>
>>
>>Changes from v1:
>>- Split up the patch moving core code to rpmsg_core into several commits
>>- Dropped the wrapping struct in rpmsg_core and just added the ops to the
>> public API (but hid the implementation details)
>>- Reordered things to reduce the size of the later patches
>>
>>Bjorn Andersson (17):
>> 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: Make rpmsg_create_ept() take channel_info struct
>> rpmsg: Clean up rpmsg device vs channel naming
>> rpmsg: Introduce indirection table for rpmsg_device operations
>> rpmsg: Move rpmsg_device API to new file
>> rpmsg: Indirection table for rpmsg_endpoint operations
>> rpmsg: Move endpoint related interface to rpmsg core
>> rpmsg: Move helper for finding rpmsg devices to core
>> rpmsg: Split off generic tail of create_channel()
>> rpmsg: Split rpmsg core and virtio backend
>> rpmsg: Hide rpmsg indirection tables
>> rpmsg: virtio: Hide vrp pointer from the public API
>> rpmsg: Move virtio specifics from public header
>> rpmsg: Allow callback to return errors
>> rpmsg: Introduce Qualcomm SMD backend
>>
>>drivers/remoteproc/Kconfig          |    4 +-
>>drivers/rpmsg/Kconfig               |   14 +
>>drivers/rpmsg/Makefile              |    4 +-
>>drivers/rpmsg/qcom_smd.c            | 1434 +++++++++++++++++++++++++++++++++++
>>drivers/rpmsg/rpmsg_core.c          |  498 ++++++++++++
>>drivers/rpmsg/rpmsg_internal.h      |   82 ++
>>drivers/rpmsg/virtio_rpmsg_bus.c    |  487 +++++-------
>>include/linux/rpmsg.h               |  246 +-----
>>samples/rpmsg/rpmsg_client_sample.c |   14 +-
>>9 files changed, 2266 insertions(+), 517 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
>>
>>--
>>To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" 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] 68+ messages in thread

* [PATCH v2 00/17] Make rpmsg a framework
@ 2016-09-12 22:22     ` Lina Iyer
  0 siblings, 0 replies; 68+ messages in thread
From: Lina Iyer @ 2016-09-12 22:22 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Sep 12 2016 at 10:52 -0600, Lina Iyer wrote:
>Hi Bjorn,
>
>On Thu, Sep 01 2016 at 16:28 -0600, Bjorn Andersson wrote:
>>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.
>>
>
>RPM Communication has to supported even when IRQs are disabled. The most
>important use of this communication is to set the wake up time for the
>CPU subsystem when all the CPUs are powered off. In addition to that,
>"sleep" votes that are sent by the application processor subsystem to
>allow system to go into deep sleep modes can only be triggered when the
>CPU PM domains are power collapsed, drivers do not have a knowledge of
>when that happens. This has to be done by a platform code that registers
>for CPU PM domain power_off/on callbacks.
>
Ok, my bad. These two cases are not critical for the SoC supported by
this driver. So you are good to go from cpuidle perspective

>Using rpmsg may be nice for RPM SMD communication, but mutexes need to
>go away for this driver to be any useful than bare bones active mode
>resource requests for QCOM SoCs. By not doing that now, we lock
>ourselves out of using this SMD driver in the near future when CPU PM
>domains are available in the kernel with an ability to do system low
>power modes.
>
>I hope you would make rpmsg work in IRQ disabled contexts first before
>porting the SMD driver.
>
>Thanks,
>Lina
>
>>
>>Changes from v1:
>>- Split up the patch moving core code to rpmsg_core into several commits
>>- Dropped the wrapping struct in rpmsg_core and just added the ops to the
>> public API (but hid the implementation details)
>>- Reordered things to reduce the size of the later patches
>>
>>Bjorn Andersson (17):
>> 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: Make rpmsg_create_ept() take channel_info struct
>> rpmsg: Clean up rpmsg device vs channel naming
>> rpmsg: Introduce indirection table for rpmsg_device operations
>> rpmsg: Move rpmsg_device API to new file
>> rpmsg: Indirection table for rpmsg_endpoint operations
>> rpmsg: Move endpoint related interface to rpmsg core
>> rpmsg: Move helper for finding rpmsg devices to core
>> rpmsg: Split off generic tail of create_channel()
>> rpmsg: Split rpmsg core and virtio backend
>> rpmsg: Hide rpmsg indirection tables
>> rpmsg: virtio: Hide vrp pointer from the public API
>> rpmsg: Move virtio specifics from public header
>> rpmsg: Allow callback to return errors
>> rpmsg: Introduce Qualcomm SMD backend
>>
>>drivers/remoteproc/Kconfig          |    4 +-
>>drivers/rpmsg/Kconfig               |   14 +
>>drivers/rpmsg/Makefile              |    4 +-
>>drivers/rpmsg/qcom_smd.c            | 1434 +++++++++++++++++++++++++++++++++++
>>drivers/rpmsg/rpmsg_core.c          |  498 ++++++++++++
>>drivers/rpmsg/rpmsg_internal.h      |   82 ++
>>drivers/rpmsg/virtio_rpmsg_bus.c    |  487 +++++-------
>>include/linux/rpmsg.h               |  246 +-----
>>samples/rpmsg/rpmsg_client_sample.c |   14 +-
>>9 files changed, 2266 insertions(+), 517 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
>>
>>--
>>To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" 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] 68+ messages in thread

* Re: [PATCH v2 00/17] Make rpmsg a framework
  2016-09-12 22:22     ` Lina Iyer
@ 2016-09-12 22:58       ` Bjorn Andersson
  -1 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-12 22:58 UTC (permalink / raw)
  To: Lina Iyer
  Cc: Ohad Ben-Cohen, linux-remoteproc, linux-arm-msm,
	linux-arm-kernel, linux-kernel

On Mon 12 Sep 15:22 PDT 2016, Lina Iyer wrote:

> On Mon, Sep 12 2016 at 10:52 -0600, Lina Iyer wrote:
> >Hi Bjorn,
> >
> >On Thu, Sep 01 2016 at 16:28 -0600, Bjorn Andersson wrote:
> >>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.
> >>
> >
> >RPM Communication has to supported even when IRQs are disabled. The most
> >important use of this communication is to set the wake up time for the
> >CPU subsystem when all the CPUs are powered off. In addition to that,
> >"sleep" votes that are sent by the application processor subsystem to
> >allow system to go into deep sleep modes can only be triggered when the
> >CPU PM domains are power collapsed, drivers do not have a knowledge of
> >when that happens. This has to be done by a platform code that registers
> >for CPU PM domain power_off/on callbacks.
> >
> Ok, my bad. These two cases are not critical for the SoC supported by
> this driver. So you are good to go from cpuidle perspective
> 

Thanks for letting me know. Please keep me updated if you find any
changes to this.

Just to be clear, I'm not against supporting sending and receiving
messages in atomic context as long as it doesn't just add accidental
complexity.

Regards,
Bjorn

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

* [PATCH v2 00/17] Make rpmsg a framework
@ 2016-09-12 22:58       ` Bjorn Andersson
  0 siblings, 0 replies; 68+ messages in thread
From: Bjorn Andersson @ 2016-09-12 22:58 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon 12 Sep 15:22 PDT 2016, Lina Iyer wrote:

> On Mon, Sep 12 2016 at 10:52 -0600, Lina Iyer wrote:
> >Hi Bjorn,
> >
> >On Thu, Sep 01 2016 at 16:28 -0600, Bjorn Andersson wrote:
> >>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.
> >>
> >
> >RPM Communication has to supported even when IRQs are disabled. The most
> >important use of this communication is to set the wake up time for the
> >CPU subsystem when all the CPUs are powered off. In addition to that,
> >"sleep" votes that are sent by the application processor subsystem to
> >allow system to go into deep sleep modes can only be triggered when the
> >CPU PM domains are power collapsed, drivers do not have a knowledge of
> >when that happens. This has to be done by a platform code that registers
> >for CPU PM domain power_off/on callbacks.
> >
> Ok, my bad. These two cases are not critical for the SoC supported by
> this driver. So you are good to go from cpuidle perspective
> 

Thanks for letting me know. Please keep me updated if you find any
changes to this.

Just to be clear, I'm not against supporting sending and receiving
messages in atomic context as long as it doesn't just add accidental
complexity.

Regards,
Bjorn

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

end of thread, other threads:[~2016-09-12 22:58 UTC | newest]

Thread overview: 68+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-01 22:27 [PATCH v2 00/17] Make rpmsg a framework Bjorn Andersson
2016-09-01 22:27 ` Bjorn Andersson
2016-09-01 22:27 ` [PATCH v2 01/17] rpmsg: Enable matching devices with drivers based on DT Bjorn Andersson
2016-09-01 22:27   ` Bjorn Andersson
2016-09-01 22:27   ` Bjorn Andersson
2016-09-08  1:46   ` spjoshi
2016-09-08  1:46     ` spjoshi at codeaurora.org
2016-09-09  4:30     ` Bjorn Andersson
2016-09-09  4:30       ` Bjorn Andersson
2016-09-09 22:07       ` Sarangdhar Joshi
2016-09-09 22:07         ` Sarangdhar Joshi
2016-09-01 22:27 ` [PATCH v2 02/17] rpmsg: Name rpmsg devices based on channel id Bjorn Andersson
2016-09-01 22:27   ` Bjorn Andersson
2016-09-01 22:27   ` Bjorn Andersson
2016-09-08  1:46   ` spjoshi
2016-09-08  1:46     ` spjoshi at codeaurora.org
2016-09-01 22:27 ` [PATCH v2 03/17] rpmsg: rpmsg_send() operations takes rpmsg_endpoint Bjorn Andersson
2016-09-01 22:27   ` Bjorn Andersson
2016-09-01 22:27 ` [PATCH v2 04/17] rpmsg: Make rpmsg_create_ept() take channel_info struct Bjorn Andersson
2016-09-01 22:27   ` Bjorn Andersson
2016-09-01 22:27   ` Bjorn Andersson
2016-09-01 22:27 ` [PATCH v2 05/17] rpmsg: Clean up rpmsg device vs channel naming Bjorn Andersson
2016-09-01 22:27   ` Bjorn Andersson
2016-09-01 22:27   ` Bjorn Andersson
2016-09-01 22:27 ` [PATCH v2 06/17] rpmsg: Introduce indirection table for rpmsg_device operations Bjorn Andersson
2016-09-01 22:27   ` Bjorn Andersson
2016-09-01 22:27 ` [PATCH v2 07/17] rpmsg: Move rpmsg_device API to new file Bjorn Andersson
2016-09-01 22:27   ` Bjorn Andersson
2016-09-01 22:28 ` [PATCH v2 08/17] rpmsg: Indirection table for rpmsg_endpoint operations Bjorn Andersson
2016-09-01 22:28   ` Bjorn Andersson
2016-09-01 22:28 ` [PATCH v2 09/17] rpmsg: Move endpoint related interface to rpmsg core Bjorn Andersson
2016-09-01 22:28   ` Bjorn Andersson
2016-09-01 22:28 ` [PATCH v2 10/17] rpmsg: Move helper for finding rpmsg devices to core Bjorn Andersson
2016-09-01 22:28   ` Bjorn Andersson
2016-09-01 22:28 ` [PATCH v2 11/17] rpmsg: Split off generic tail of create_channel() Bjorn Andersson
2016-09-01 22:28   ` Bjorn Andersson
2016-09-01 22:28 ` [PATCH v2 12/17] rpmsg: Split rpmsg core and virtio backend Bjorn Andersson
2016-09-01 22:28   ` Bjorn Andersson
2016-09-01 22:28 ` [PATCH v2 13/17] rpmsg: Hide rpmsg indirection tables Bjorn Andersson
2016-09-01 22:28   ` Bjorn Andersson
2016-09-01 22:28 ` [PATCH v2 14/17] rpmsg: virtio: Hide vrp pointer from the public API Bjorn Andersson
2016-09-01 22:28   ` Bjorn Andersson
2016-09-01 22:28 ` [PATCH v2 15/17] rpmsg: Move virtio specifics from public header Bjorn Andersson
2016-09-01 22:28   ` Bjorn Andersson
2016-09-01 22:28 ` [PATCH v2 16/17] rpmsg: Allow callback to return errors Bjorn Andersson
2016-09-01 22:28   ` Bjorn Andersson
2016-09-01 22:28 ` [PATCH v2 17/17] rpmsg: Introduce Qualcomm SMD backend Bjorn Andersson
2016-09-01 22:28   ` Bjorn Andersson
2016-09-12 16:52 ` [PATCH v2 00/17] Make rpmsg a framework Lina Iyer
2016-09-12 16:52   ` Lina Iyer
2016-09-12 18:00   ` Bjorn Andersson
2016-09-12 18:00     ` Bjorn Andersson
2016-09-12 18:13     ` Jeffrey Hugo
2016-09-12 18:13       ` Jeffrey Hugo
2016-09-12 18:49       ` Bjorn Andersson
2016-09-12 18:49         ` Bjorn Andersson
2016-09-12 19:21         ` Jeffrey Hugo
2016-09-12 19:21           ` Jeffrey Hugo
2016-09-12 19:58           ` Bjorn Andersson
2016-09-12 19:58             ` Bjorn Andersson
2016-09-12 21:36             ` Karthikeyan Ramasubramanian
2016-09-12 21:36               ` Karthikeyan Ramasubramanian
2016-09-12 21:53               ` Bjorn Andersson
2016-09-12 21:53                 ` Bjorn Andersson
2016-09-12 22:22   ` Lina Iyer
2016-09-12 22:22     ` Lina Iyer
2016-09-12 22:58     ` Bjorn Andersson
2016-09-12 22:58       ` 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.