From 2bfc03f636aa6fbd1806ff0897b0fbd8ca7c9810 Mon Sep 17 00:00:00 2001 From: Xiang Xiao Date: Tue, 21 Apr 2020 20:37:06 +0800 Subject: [PATCH] openamp: Download libmetal and open-amp from github and apply the patch which is pending merge to upstream Signed-off-by: Xiang Xiao --- openamp/.gitignore | 3 + ...nge-sched_kfree-to-metal_free_memory.patch | 29 + ...-address-check-in-rpmsg_send-rpmsg_t.patch | 38 + ...g_register_endpoint-into-rpmsg_init_.patch | 128 +++ ...allocate-0-1023-address-in-rpmsg_cre.patch | 227 +++++ ...4-rpmsg-wait-ept-ready-in-rpmsg_send.patch | 128 +++ ...l-if-either-source-or-destination-ad.patch | 45 + ..._mmap-support-va-to-pa-da-conversion.patch | 785 ++++++++++++++++++ ...-rpmsg-bring-back-zero-copy-transfer.patch | 470 +++++++++++ ...wledge-the-received-creation-message.patch | 132 +++ ...virtio_read_config-rproc_virtio_writ.patch | 119 +++ ...e-individual-buffer-size-dynamically.patch | 159 ++++ openamp/Makefile | 3 +- openamp/libmetal.defs | 29 +- openamp/open-amp.defs | 24 +- 15 files changed, 2303 insertions(+), 16 deletions(-) create mode 100644 openamp/0001-nuttx-change-sched_kfree-to-metal_free_memory.patch create mode 100644 openamp/0001-rpmsg-remove-the-address-check-in-rpmsg_send-rpmsg_t.patch create mode 100644 openamp/0002-rpmsg-merge-rpmsg_register_endpoint-into-rpmsg_init_.patch create mode 100644 openamp/0003-rpmsg-shouldn-t-allocate-0-1023-address-in-rpmsg_cre.patch create mode 100644 openamp/0004-rpmsg-wait-ept-ready-in-rpmsg_send.patch create mode 100644 openamp/0005-rpmsg-return-fail-if-either-source-or-destination-ad.patch create mode 100644 openamp/0006-remoteproc_mmap-support-va-to-pa-da-conversion.patch create mode 100644 openamp/0007-rpmsg-bring-back-zero-copy-transfer.patch create mode 100644 openamp/0008-ns-acknowledge-the-received-creation-message.patch create mode 100644 openamp/0009-implement-rproc_virtio_read_config-rproc_virtio_writ.patch create mode 100644 openamp/0010-Negotiate-individual-buffer-size-dynamically.patch diff --git a/openamp/.gitignore b/openamp/.gitignore index 95c5cfa399..95e004281a 100644 --- a/openamp/.gitignore +++ b/openamp/.gitignore @@ -1,4 +1,7 @@ /.libmetal_headers /.openamp_headers +/.depend +/Make.dep /libmetal /open-amp +/*.zip diff --git a/openamp/0001-nuttx-change-sched_kfree-to-metal_free_memory.patch b/openamp/0001-nuttx-change-sched_kfree-to-metal_free_memory.patch new file mode 100644 index 0000000000..94a848df37 --- /dev/null +++ b/openamp/0001-nuttx-change-sched_kfree-to-metal_free_memory.patch @@ -0,0 +1,29 @@ +From e84d8dd13d31de4942bbf4ec8093932961b9d1b9 Mon Sep 17 00:00:00 2001 +From: Xiang Xiao +Date: Tue, 21 Apr 2020 22:02:38 +0800 +Subject: [PATCH] nuttx: change sched_kfree to metal_free_memory + +since the upstream remove sched_kfree and put the similar logic into kmm_free: +https://github.com/apache/incubator-nuttx/commit/231ad202ee0a3abfd2e14fab1f218b588f61284b + +Signed-off-by: Xiang Xiao +--- + lib/system/nuttx/irq.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/system/nuttx/irq.c libmetal/lib/system/nuttx/irq.c +index 476eab9..84200d3 100644 +--- a/lib/system/nuttx/irq.c ++++ libmetal/lib/system/nuttx/irq.c +@@ -45,7 +45,7 @@ static int metal_cntr_irq_handler(int irq, void *context, void *data) + + /* context == NULL mean unregister */ + irqchain_detach(irq, metal_cntr_irq_handler, data); +- sched_kfree(data); ++ metal_free_memory(data); + return 0; + } + +-- +2.17.1 + diff --git a/openamp/0001-rpmsg-remove-the-address-check-in-rpmsg_send-rpmsg_t.patch b/openamp/0001-rpmsg-remove-the-address-check-in-rpmsg_send-rpmsg_t.patch new file mode 100644 index 0000000000..023d244a4a --- /dev/null +++ b/openamp/0001-rpmsg-remove-the-address-check-in-rpmsg_send-rpmsg_t.patch @@ -0,0 +1,38 @@ +From aca01202ec47984ea90d3904560b973976cab1e5 Mon Sep 17 00:00:00 2001 +From: Xiang Xiao +Date: Fri, 24 Apr 2020 01:44:31 +0800 +Subject: [PATCH 01/10] rpmsg: remove the address check in + rpmsg_send/rpmsg_trysend + +since rpmsg_send_offchannel_raw already do the same validation + +Signed-off-by: Xiang Xiao +--- + lib/include/openamp/rpmsg.h | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/lib/include/openamp/rpmsg.h open-amp/lib/include/openamp/rpmsg.h +index f2a6454..8401c38 100644 +--- a/lib/include/openamp/rpmsg.h ++++ open-amp/lib/include/openamp/rpmsg.h +@@ -146,8 +146,6 @@ int rpmsg_send_offchannel_raw(struct rpmsg_endpoint *ept, uint32_t src, + static inline int rpmsg_send(struct rpmsg_endpoint *ept, const void *data, + int len) + { +- if (ept->dest_addr == RPMSG_ADDR_ANY) +- return RPMSG_ERR_ADDR; + return rpmsg_send_offchannel_raw(ept, ept->addr, ept->dest_addr, data, + len, true); + } +@@ -216,8 +214,6 @@ static inline int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, + static inline int rpmsg_trysend(struct rpmsg_endpoint *ept, const void *data, + int len) + { +- if (ept->dest_addr == RPMSG_ADDR_ANY) +- return RPMSG_ERR_ADDR; + return rpmsg_send_offchannel_raw(ept, ept->addr, ept->dest_addr, data, + len, false); + } +-- +2.17.1 + diff --git a/openamp/0002-rpmsg-merge-rpmsg_register_endpoint-into-rpmsg_init_.patch b/openamp/0002-rpmsg-merge-rpmsg_register_endpoint-into-rpmsg_init_.patch new file mode 100644 index 0000000000..52a1f57592 --- /dev/null +++ b/openamp/0002-rpmsg-merge-rpmsg_register_endpoint-into-rpmsg_init_.patch @@ -0,0 +1,128 @@ +From c4c3577a3d7a1e957c84f86caa64b7e076b9db89 Mon Sep 17 00:00:00 2001 +From: Xiang Xiao +Date: Fri, 24 Apr 2020 03:40:56 +0800 +Subject: [PATCH 02/10] rpmsg: merge rpmsg_register_endpoint into + rpmsg_init_ept + +so the service which use preserved address could call rpmsg_init_ept + +Signed-off-by: Xiang Xiao +--- + lib/include/openamp/rpmsg.h | 19 +++++++------------ + lib/rpmsg/rpmsg.c | 17 +++++++++++++---- + lib/rpmsg/rpmsg_internal.h | 2 -- + lib/rpmsg/rpmsg_virtio.c | 3 +-- + 4 files changed, 21 insertions(+), 20 deletions(-) + +diff --git a/lib/include/openamp/rpmsg.h open-amp/lib/include/openamp/rpmsg.h +index 8401c38..a08f9d3 100644 +--- a/lib/include/openamp/rpmsg.h ++++ open-amp/lib/include/openamp/rpmsg.h +@@ -271,6 +271,7 @@ static inline int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, + * remoteproc address, endpoint callback, and destroy endpoint callback. + * + * @ept: pointer to rpmsg endpoint ++ * @rdev: pointer to the rpmsg device + * @name: service name associated to the endpoint + * @src: local address of the endpoint + * @dest: target address of the endpoint +@@ -278,18 +279,12 @@ static inline int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, + * @ns_unbind_cb: end point service unbind callback, called when remote ept is + * destroyed. + */ +-static inline void rpmsg_init_ept(struct rpmsg_endpoint *ept, +- const char *name, +- uint32_t src, uint32_t dest, +- rpmsg_ept_cb cb, +- rpmsg_ns_unbind_cb ns_unbind_cb) +-{ +- strncpy(ept->name, name ? name : "", sizeof(ept->name)); +- ept->addr = src; +- ept->dest_addr = dest; +- ept->cb = cb; +- ept->ns_unbind_cb = ns_unbind_cb; +-} ++void rpmsg_init_ept(struct rpmsg_endpoint *ept, ++ struct rpmsg_device *rdev, ++ const char *name, ++ uint32_t src, uint32_t dest, ++ rpmsg_ept_cb cb, ++ rpmsg_ns_unbind_cb ns_unbind_cb); + + /** + * rpmsg_create_ept - create rpmsg endpoint and register it to rpmsg device +diff --git a/lib/rpmsg/rpmsg.c open-amp/lib/rpmsg/rpmsg.c +index 5b9c735..eee1c28 100644 +--- a/lib/rpmsg/rpmsg.c ++++ open-amp/lib/rpmsg/rpmsg.c +@@ -182,6 +182,7 @@ static void rpmsg_unregister_endpoint(struct rpmsg_endpoint *ept) + return; + + rdev = ept->rdev; ++ ept->rdev = NULL; + + if (ept->addr != RPMSG_ADDR_ANY) + rpmsg_release_address(rdev->bitmap, RPMSG_ADDR_BMP_SIZE, +@@ -189,9 +190,18 @@ static void rpmsg_unregister_endpoint(struct rpmsg_endpoint *ept) + metal_list_del(&ept->node); + } + +-void rpmsg_register_endpoint(struct rpmsg_device *rdev, +- struct rpmsg_endpoint *ept) ++void rpmsg_init_ept(struct rpmsg_endpoint *ept, ++ struct rpmsg_device *rdev, ++ const char *name, ++ uint32_t src, uint32_t dest, ++ rpmsg_ept_cb cb, ++ rpmsg_ns_unbind_cb ns_unbind_cb) + { ++ strncpy(ept->name, name ? name : "", sizeof(ept->name)); ++ ept->addr = src; ++ ept->dest_addr = dest; ++ ept->cb = cb; ++ ept->ns_unbind_cb = ns_unbind_cb; + ept->rdev = rdev; + metal_list_add_tail(&rdev->endpoints, &ept->node); + } +@@ -224,8 +234,7 @@ int rpmsg_create_ept(struct rpmsg_endpoint *ept, struct rpmsg_device *rdev, + addr = rpmsg_get_address(rdev->bitmap, RPMSG_ADDR_BMP_SIZE); + } + +- rpmsg_init_ept(ept, name, addr, dest, cb, unbind_cb); +- rpmsg_register_endpoint(rdev, ept); ++ rpmsg_init_ept(ept, rdev, name, addr, dest, cb, unbind_cb); + + if (rdev->support_ns && ept->dest_addr == RPMSG_ADDR_ANY) { + /* Send NS announcement to remote processor */ +diff --git a/lib/rpmsg/rpmsg_internal.h open-amp/lib/rpmsg/rpmsg_internal.h +index f63c958..9c46970 100644 +--- a/lib/rpmsg/rpmsg_internal.h ++++ open-amp/lib/rpmsg/rpmsg_internal.h +@@ -92,8 +92,6 @@ int rpmsg_send_ns_message(struct rpmsg_endpoint *ept, unsigned long flags); + struct rpmsg_endpoint *rpmsg_get_endpoint(struct rpmsg_device *rvdev, + const char *name, uint32_t addr, + uint32_t dest_addr); +-void rpmsg_register_endpoint(struct rpmsg_device *rdev, +- struct rpmsg_endpoint *ept); + + static inline struct rpmsg_endpoint * + rpmsg_get_ept_from_addr(struct rpmsg_device *rdev, uint32_t addr) +diff --git a/lib/rpmsg/rpmsg_virtio.c open-amp/lib/rpmsg/rpmsg_virtio.c +index cf3ec21..ff1226b 100644 +--- a/lib/rpmsg/rpmsg_virtio.c ++++ open-amp/lib/rpmsg/rpmsg_virtio.c +@@ -636,10 +636,9 @@ int rpmsg_init_vdev(struct rpmsg_virtio_device *rvdev, + * service announcement feature. + */ + if (rdev->support_ns) { +- rpmsg_init_ept(&rdev->ns_ept, "NS", ++ rpmsg_init_ept(&rdev->ns_ept, rdev, "NS", + RPMSG_NS_EPT_ADDR, RPMSG_NS_EPT_ADDR, + rpmsg_virtio_ns_callback, NULL); +- rpmsg_register_endpoint(rdev, &rdev->ns_ept); + } + + #ifndef VIRTIO_SLAVE_ONLY +-- +2.17.1 + diff --git a/openamp/0003-rpmsg-shouldn-t-allocate-0-1023-address-in-rpmsg_cre.patch b/openamp/0003-rpmsg-shouldn-t-allocate-0-1023-address-in-rpmsg_cre.patch new file mode 100644 index 0000000000..b550c0d592 --- /dev/null +++ b/openamp/0003-rpmsg-shouldn-t-allocate-0-1023-address-in-rpmsg_cre.patch @@ -0,0 +1,227 @@ +From 373d773c188920088af1673867de5cfed12ea4de Mon Sep 17 00:00:00 2001 +From: Xiang Xiao +Date: Fri, 24 Apr 2020 01:33:12 +0800 +Subject: [PATCH 03/10] rpmsg: shouldn't allocate 0-1023 address in + rpmsg_create_ept + +since this region is reserved for predefined services(e.g. NS use 0x35) + +Signed-off-by: Xiang Xiao +--- + apps/examples/echo/rpmsg-echo.c | 2 +- + apps/examples/echo/rpmsg-ping.c | 2 +- + .../matrix_multiply/matrix_multiply.c | 2 +- + .../matrix_multiply/matrix_multiplyd.c | 2 +- + apps/examples/rpc_demo/rpc_demod.c | 2 +- + .../rpmsg_sample_echo/rpmsg-sample-ping.c | 2 +- + apps/tests/msg/rpmsg-flood-ping.c | 2 +- + apps/tests/msg/rpmsg-ping.c | 2 +- + apps/tests/msg/rpmsg-update.c | 2 +- + lib/include/openamp/rpmsg.h | 27 ++++++++++--------- + lib/rpmsg/rpmsg.c | 11 +++++--- + 11 files changed, 30 insertions(+), 26 deletions(-) + +diff --git a/apps/examples/echo/rpmsg-echo.c open-amp/apps/examples/echo/rpmsg-echo.c +index 0c75203..71a0bbf 100644 +--- a/apps/examples/echo/rpmsg-echo.c ++++ open-amp/apps/examples/echo/rpmsg-echo.c +@@ -58,7 +58,7 @@ int app(struct rpmsg_device *rdev, void *priv) + LPRINTF("Try to create rpmsg endpoint.\r\n"); + + ret = rpmsg_create_ept(&lept, rdev, RPMSG_SERVICE_NAME, +- 0, RPMSG_ADDR_ANY, rpmsg_endpoint_cb, ++ 1024, RPMSG_ADDR_ANY, rpmsg_endpoint_cb, + rpmsg_service_unbind); + if (ret) { + LPERROR("Failed to create endpoint.\r\n"); +diff --git a/apps/examples/echo/rpmsg-ping.c open-amp/apps/examples/echo/rpmsg-ping.c +index 3b716b0..ff639cd 100644 +--- a/apps/examples/echo/rpmsg-ping.c ++++ open-amp/apps/examples/echo/rpmsg-ping.c +@@ -11,7 +11,7 @@ This application echoes back data that was sent to it by the master core. */ + #include "platform_info.h" + #include "rpmsg-echo.h" + +-#define APP_EPT_ADDR 0 ++#define APP_EPT_ADDR 1024 + #define LPRINTF(format, ...) printf(format, ##__VA_ARGS__) + #define LPERROR(format, ...) LPRINTF("ERROR: " format, ##__VA_ARGS__) + +diff --git a/apps/examples/matrix_multiply/matrix_multiply.c open-amp/apps/examples/matrix_multiply/matrix_multiply.c +index b9da29b..3928088 100644 +--- a/apps/examples/matrix_multiply/matrix_multiply.c ++++ open-amp/apps/examples/matrix_multiply/matrix_multiply.c +@@ -14,7 +14,7 @@ multiplies them and returns the result to the master core. */ + + #define MAX_SIZE 6 + #define NUM_MATRIX 2 +-#define APP_EPT_ADDR 0 ++#define APP_EPT_ADDR 1024 + + #define raw_printf(format, ...) printf(format, ##__VA_ARGS__) + #define LPRINTF(format, ...) raw_printf("CLIENT> " format, ##__VA_ARGS__) +diff --git a/apps/examples/matrix_multiply/matrix_multiplyd.c open-amp/apps/examples/matrix_multiply/matrix_multiplyd.c +index 6b4a118..29c6380 100644 +--- a/apps/examples/matrix_multiply/matrix_multiplyd.c ++++ open-amp/apps/examples/matrix_multiply/matrix_multiplyd.c +@@ -92,7 +92,7 @@ int app(struct rpmsg_device *rdev, void *priv) + int ret; + + ret = rpmsg_create_ept(&lept, rdev, RPMSG_SERVICE_NAME, +- 0, RPMSG_ADDR_ANY, rpmsg_endpoint_cb, ++ 1024, RPMSG_ADDR_ANY, rpmsg_endpoint_cb, + rpmsg_service_unbind); + if (ret) { + LPERROR("Failed to create endpoint.\r\n"); +diff --git a/apps/examples/rpc_demo/rpc_demod.c open-amp/apps/examples/rpc_demo/rpc_demod.c +index 44c92a2..a4659f3 100644 +--- a/apps/examples/rpc_demo/rpc_demod.c ++++ open-amp/apps/examples/rpc_demo/rpc_demod.c +@@ -312,7 +312,7 @@ int app(struct rpmsg_device *rdev, void *priv) + LPRINTF("Try to create rpmsg endpoint.\r\n"); + + ret = rpmsg_create_ept(&app_ept, rdev, RPMSG_SERVICE_NAME, +- 0, RPMSG_ADDR_ANY, rpmsg_endpoint_cb, ++ 1024, RPMSG_ADDR_ANY, rpmsg_endpoint_cb, + rpmsg_service_unbind); + if (ret) { + LPERROR("Failed to create endpoint.\r\n"); +diff --git a/apps/examples/rpmsg_sample_echo/rpmsg-sample-ping.c open-amp/apps/examples/rpmsg_sample_echo/rpmsg-sample-ping.c +index ee866b4..14456e3 100644 +--- a/apps/examples/rpmsg_sample_echo/rpmsg-sample-ping.c ++++ open-amp/apps/examples/rpmsg_sample_echo/rpmsg-sample-ping.c +@@ -20,7 +20,7 @@ + #define BYE_MSG "goodbye!" + #define MSG_LIMIT 100 + +-#define APP_EPT_ADDR 0 ++#define APP_EPT_ADDR 1024 + #define LPRINTF(format, ...) printf(format, ##__VA_ARGS__) + #define LPERROR(format, ...) LPRINTF("ERROR: " format, ##__VA_ARGS__) + +diff --git a/apps/tests/msg/rpmsg-flood-ping.c open-amp/apps/tests/msg/rpmsg-flood-ping.c +index 66489f8..28edc66 100644 +--- a/apps/tests/msg/rpmsg-flood-ping.c ++++ open-amp/apps/tests/msg/rpmsg-flood-ping.c +@@ -12,7 +12,7 @@ + #include "platform_info.h" + #include "rpmsg-ping.h" + +-#define APP_EPT_ADDR 0 ++#define APP_EPT_ADDR 1024 + #define LPRINTF(format, ...) printf(format, ##__VA_ARGS__) + #define LPERROR(format, ...) LPRINTF("ERROR: " format, ##__VA_ARGS__) + +diff --git a/apps/tests/msg/rpmsg-ping.c open-amp/apps/tests/msg/rpmsg-ping.c +index 0220a27..752b16c 100644 +--- a/apps/tests/msg/rpmsg-ping.c ++++ open-amp/apps/tests/msg/rpmsg-ping.c +@@ -11,7 +11,7 @@ This application echoes back data that was sent to it by the master core. */ + #include "platform_info.h" + #include "rpmsg-ping.h" + +-#define APP_EPT_ADDR 0 ++#define APP_EPT_ADDR 1024 + #define LPRINTF(format, ...) printf(format, ##__VA_ARGS__) + #define LPERROR(format, ...) LPRINTF("ERROR: " format, ##__VA_ARGS__) + +diff --git a/apps/tests/msg/rpmsg-update.c open-amp/apps/tests/msg/rpmsg-update.c +index 9b26cac..b8e08db 100644 +--- a/apps/tests/msg/rpmsg-update.c ++++ open-amp/apps/tests/msg/rpmsg-update.c +@@ -73,7 +73,7 @@ int app(struct rpmsg_device *rdev, void *priv) + LPRINTF("Try to create rpmsg endpoint.\r\n"); + + ret = rpmsg_create_ept(&lept, rdev, RPMSG_SERVICE_NAME, +- 0, RPMSG_ADDR_ANY, rpmsg_endpoint_cb, ++ 1024, RPMSG_ADDR_ANY, rpmsg_endpoint_cb, + rpmsg_service_unbind); + if (ret) { + LPERROR("Failed to create endpoint.\r\n"); +diff --git a/lib/include/openamp/rpmsg.h open-amp/lib/include/openamp/rpmsg.h +index a08f9d3..3403240 100644 +--- a/lib/include/openamp/rpmsg.h ++++ open-amp/lib/include/openamp/rpmsg.h +@@ -25,22 +25,23 @@ extern "C" { + #endif + + /* Configurable parameters */ +-#define RPMSG_NAME_SIZE (32) +-#define RPMSG_ADDR_BMP_SIZE (128) ++#define RPMSG_NAME_SIZE (32) ++#define RPMSG_ADDR_BMP_SIZE (128) + +-#define RPMSG_NS_EPT_ADDR (0x35) +-#define RPMSG_ADDR_ANY 0xFFFFFFFF ++#define RPMSG_NS_EPT_ADDR (0x35) ++#define RPMSG_RESERVED_ADDRESSES (1024) ++#define RPMSG_ADDR_ANY 0xFFFFFFFF + + /* Error macros. */ +-#define RPMSG_SUCCESS 0 +-#define RPMSG_ERROR_BASE -2000 +-#define RPMSG_ERR_NO_MEM (RPMSG_ERROR_BASE - 1) +-#define RPMSG_ERR_NO_BUFF (RPMSG_ERROR_BASE - 2) +-#define RPMSG_ERR_PARAM (RPMSG_ERROR_BASE - 3) +-#define RPMSG_ERR_DEV_STATE (RPMSG_ERROR_BASE - 4) +-#define RPMSG_ERR_BUFF_SIZE (RPMSG_ERROR_BASE - 5) +-#define RPMSG_ERR_INIT (RPMSG_ERROR_BASE - 6) +-#define RPMSG_ERR_ADDR (RPMSG_ERROR_BASE - 7) ++#define RPMSG_SUCCESS 0 ++#define RPMSG_ERROR_BASE -2000 ++#define RPMSG_ERR_NO_MEM (RPMSG_ERROR_BASE - 1) ++#define RPMSG_ERR_NO_BUFF (RPMSG_ERROR_BASE - 2) ++#define RPMSG_ERR_PARAM (RPMSG_ERROR_BASE - 3) ++#define RPMSG_ERR_DEV_STATE (RPMSG_ERROR_BASE - 4) ++#define RPMSG_ERR_BUFF_SIZE (RPMSG_ERROR_BASE - 5) ++#define RPMSG_ERR_INIT (RPMSG_ERROR_BASE - 6) ++#define RPMSG_ERR_ADDR (RPMSG_ERROR_BASE - 7) + + struct rpmsg_endpoint; + struct rpmsg_device; +diff --git a/lib/rpmsg/rpmsg.c open-amp/lib/rpmsg/rpmsg.c +index eee1c28..dcc39c1 100644 +--- a/lib/rpmsg/rpmsg.c ++++ open-amp/lib/rpmsg/rpmsg.c +@@ -29,7 +29,7 @@ static uint32_t rpmsg_get_address(unsigned long *bitmap, int size) + + nextbit = metal_bitmap_next_clear_bit(bitmap, 0, size); + if (nextbit < (uint32_t)size) { +- addr = nextbit; ++ addr = RPMSG_RESERVED_ADDRESSES + nextbit; + metal_bitmap_set_bit(bitmap, nextbit); + } + +@@ -48,7 +48,8 @@ static uint32_t rpmsg_get_address(unsigned long *bitmap, int size) + static void rpmsg_release_address(unsigned long *bitmap, int size, + int addr) + { +- if (addr < size) ++ addr -= RPMSG_RESERVED_ADDRESSES; ++ if (addr >= 0 && addr < size) + metal_bitmap_clear_bit(bitmap, addr); + } + +@@ -65,7 +66,8 @@ static void rpmsg_release_address(unsigned long *bitmap, int size, + */ + static int rpmsg_is_address_set(unsigned long *bitmap, int size, int addr) + { +- if (addr < size) ++ addr -= RPMSG_RESERVED_ADDRESSES; ++ if (addr >= 0 && addr < size) + return metal_bitmap_is_bit_set(bitmap, addr); + else + return RPMSG_ERR_PARAM; +@@ -84,7 +86,8 @@ static int rpmsg_is_address_set(unsigned long *bitmap, int size, int addr) + */ + static int rpmsg_set_address(unsigned long *bitmap, int size, int addr) + { +- if (addr < size) { ++ addr -= RPMSG_RESERVED_ADDRESSES; ++ if (addr >= 0 && addr < size) { + metal_bitmap_set_bit(bitmap, addr); + return RPMSG_SUCCESS; + } else { +-- +2.17.1 + diff --git a/openamp/0004-rpmsg-wait-ept-ready-in-rpmsg_send.patch b/openamp/0004-rpmsg-wait-ept-ready-in-rpmsg_send.patch new file mode 100644 index 0000000000..59d89df789 --- /dev/null +++ b/openamp/0004-rpmsg-wait-ept-ready-in-rpmsg_send.patch @@ -0,0 +1,128 @@ +From 2a82b3350bc5eb44d6ffd66da6e3bae6d15ec84c Mon Sep 17 00:00:00 2001 +From: ligd +Date: Wed, 20 Feb 2019 11:36:57 +0800 +Subject: [PATCH 04/10] rpmsg: wait ept ready in rpmsg_send + +since the destination address need time to return from peer + +Signed-off-by: ligd +--- + lib/include/openamp/rpmsg.h | 48 ++++++++++++++++++++++++------------- + lib/rpmsg/rpmsg_virtio.c | 7 ------ + 2 files changed, 32 insertions(+), 23 deletions(-) + +diff --git a/lib/include/openamp/rpmsg.h open-amp/lib/include/openamp/rpmsg.h +index 3403240..7000453 100644 +--- a/lib/include/openamp/rpmsg.h ++++ open-amp/lib/include/openamp/rpmsg.h +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -32,6 +33,12 @@ extern "C" { + #define RPMSG_RESERVED_ADDRESSES (1024) + #define RPMSG_ADDR_ANY 0xFFFFFFFF + ++/* Total tick count for 15secs - 1usec tick. */ ++#define RPMSG_TICK_COUNT 15000000 ++ ++/* Time to wait - In multiple of 1 msecs. */ ++#define RPMSG_TICKS_PER_INTERVAL 1000 ++ + /* Error macros. */ + #define RPMSG_SUCCESS 0 + #define RPMSG_ERROR_BASE -2000 +@@ -129,6 +136,20 @@ int rpmsg_send_offchannel_raw(struct rpmsg_endpoint *ept, uint32_t src, + uint32_t dst, const void *data, int size, + int wait); + ++/** ++ * is_rpmsg_ept_ready - check if the rpmsg endpoint ready to send ++ * ++ * @ept: pointer to rpmsg endpoint ++ * ++ * Returns 1 if the rpmsg endpoint has both local addr and destination ++ * addr set, 0 otherwise ++ */ ++static inline unsigned int is_rpmsg_ept_ready(struct rpmsg_endpoint *ept) ++{ ++ return (ept->dest_addr != RPMSG_ADDR_ANY) && ++ (ept->addr != RPMSG_ADDR_ANY); ++} ++ + /** + * rpmsg_send() - send a message across to the remote processor + * @ept: the rpmsg endpoint +@@ -147,8 +168,17 @@ int rpmsg_send_offchannel_raw(struct rpmsg_endpoint *ept, uint32_t src, + static inline int rpmsg_send(struct rpmsg_endpoint *ept, const void *data, + int len) + { +- return rpmsg_send_offchannel_raw(ept, ept->addr, ept->dest_addr, data, +- len, true); ++ int tc = 0; ++ ++ for (; tc < RPMSG_TICK_COUNT; tc += RPMSG_TICKS_PER_INTERVAL) { ++ if (is_rpmsg_ept_ready(ept)) ++ return rpmsg_send_offchannel_raw(ept, ept->addr, ++ ept->dest_addr, ++ data, len, true); ++ metal_sleep_usec(RPMSG_TICKS_PER_INTERVAL); ++ } ++ ++ return RPMSG_ERR_ADDR; + } + + /** +@@ -328,20 +358,6 @@ int rpmsg_create_ept(struct rpmsg_endpoint *ept, struct rpmsg_device *rdev, + */ + void rpmsg_destroy_ept(struct rpmsg_endpoint *ept); + +-/** +- * is_rpmsg_ept_ready - check if the rpmsg endpoint ready to send +- * +- * @ept: pointer to rpmsg endpoint +- * +- * Returns 1 if the rpmsg endpoint has both local addr and destination +- * addr set, 0 otherwise +- */ +-static inline unsigned int is_rpmsg_ept_ready(struct rpmsg_endpoint *ept) +-{ +- return (ept->dest_addr != RPMSG_ADDR_ANY) && +- (ept->addr != RPMSG_ADDR_ANY); +-} +- + #if defined __cplusplus + } + #endif +diff --git a/lib/rpmsg/rpmsg_virtio.c open-amp/lib/rpmsg/rpmsg_virtio.c +index ff1226b..17f2998 100644 +--- a/lib/rpmsg/rpmsg_virtio.c ++++ open-amp/lib/rpmsg/rpmsg_virtio.c +@@ -8,7 +8,6 @@ + */ + + #include +-#include + #include + #include + #include +@@ -17,12 +16,6 @@ + + #define RPMSG_NUM_VRINGS 2 + +-/* Total tick count for 15secs - 1usec tick. */ +-#define RPMSG_TICK_COUNT 15000000 +- +-/* Time to wait - In multiple of 1 msecs. */ +-#define RPMSG_TICKS_PER_INTERVAL 1000 +- + #ifndef VIRTIO_SLAVE_ONLY + metal_weak void * + rpmsg_virtio_shm_pool_get_buffer(struct rpmsg_virtio_shm_pool *shpool, +-- +2.17.1 + diff --git a/openamp/0005-rpmsg-return-fail-if-either-source-or-destination-ad.patch b/openamp/0005-rpmsg-return-fail-if-either-source-or-destination-ad.patch new file mode 100644 index 0000000000..fd4ccaf479 --- /dev/null +++ b/openamp/0005-rpmsg-return-fail-if-either-source-or-destination-ad.patch @@ -0,0 +1,45 @@ +From 8169c7954d432c6abd8db8f1bde35890bba672ff Mon Sep 17 00:00:00 2001 +From: Xiang Xiao +Date: Fri, 24 Apr 2020 02:22:15 +0800 +Subject: [PATCH 05/10] rpmsg: return fail if either source or destination + address is zero + +to help detect rpmsg_send is called before the endpoint +initialization or after the endpoint uninitialization + +Signed-off-by: Xiang Xiao +--- + lib/include/openamp/rpmsg.h | 3 +-- + lib/rpmsg/rpmsg.c | 2 +- + 2 files changed, 2 insertions(+), 3 deletions(-) + +diff --git a/lib/include/openamp/rpmsg.h open-amp/lib/include/openamp/rpmsg.h +index 7000453..1279ea2 100644 +--- a/lib/include/openamp/rpmsg.h ++++ open-amp/lib/include/openamp/rpmsg.h +@@ -146,8 +146,7 @@ int rpmsg_send_offchannel_raw(struct rpmsg_endpoint *ept, uint32_t src, + */ + static inline unsigned int is_rpmsg_ept_ready(struct rpmsg_endpoint *ept) + { +- return (ept->dest_addr != RPMSG_ADDR_ANY) && +- (ept->addr != RPMSG_ADDR_ANY); ++ return ept && ept->rdev && ept->dest_addr && ept->dest_addr != RPMSG_ADDR_ANY; + } + + /** +diff --git a/lib/rpmsg/rpmsg.c open-amp/lib/rpmsg/rpmsg.c +index dcc39c1..9da38a1 100644 +--- a/lib/rpmsg/rpmsg.c ++++ open-amp/lib/rpmsg/rpmsg.c +@@ -115,7 +115,7 @@ int rpmsg_send_offchannel_raw(struct rpmsg_endpoint *ept, uint32_t src, + { + struct rpmsg_device *rdev; + +- if (!ept || !ept->rdev || !data || dst == RPMSG_ADDR_ANY) ++ if (!ept || !ept->rdev || !data || !dst || dst == RPMSG_ADDR_ANY) + return RPMSG_ERR_PARAM; + + rdev = ept->rdev; +-- +2.17.1 + diff --git a/openamp/0006-remoteproc_mmap-support-va-to-pa-da-conversion.patch b/openamp/0006-remoteproc_mmap-support-va-to-pa-da-conversion.patch new file mode 100644 index 0000000000..e6a4fa7318 --- /dev/null +++ b/openamp/0006-remoteproc_mmap-support-va-to-pa-da-conversion.patch @@ -0,0 +1,785 @@ +From bdadd236975ba4b4d9011d3b86d528d305476cb2 Mon Sep 17 00:00:00 2001 +From: Xiang Xiao +Date: Fri, 15 Mar 2019 01:51:03 +0800 +Subject: [PATCH 06/10] remoteproc_mmap support va to pa/da conversion + +1.change va from output to input/output +2.remoteproc_get_io_xxx fallback to mmap callback + +Signed-off-by: Xiang Xiao +--- + .../load_fw/zynqmp_r5_lcm_rproc_example.c | 69 +++++------ + apps/machine/zynq7/platform_info.c | 16 +-- + apps/machine/zynq7/zynq_a9_rproc.c | 40 +++---- + apps/machine/zynqmp/platform_info.c | 6 +- + apps/machine/zynqmp/zynqmp_linux_r5_proc.c | 40 ++++--- + apps/machine/zynqmp_r5/platform_info.c | 16 +-- + apps/machine/zynqmp_r5/zynqmp_r5_a53_rproc.c | 38 +++--- + .../linux/machine/generic/platform_info.c | 52 ++++---- + lib/include/openamp/remoteproc.h | 19 +-- + lib/remoteproc/remoteproc.c | 112 ++++++++++-------- + lib/remoteproc/rsc_table_parser.c | 2 +- + 11 files changed, 212 insertions(+), 198 deletions(-) + +diff --git a/apps/examples/load_fw/zynqmp_r5_lcm_rproc_example.c open-amp/apps/examples/load_fw/zynqmp_r5_lcm_rproc_example.c +index 26a09e5..e224631 100644 +--- a/apps/examples/load_fw/zynqmp_r5_lcm_rproc_example.c ++++ open-amp/apps/examples/load_fw/zynqmp_r5_lcm_rproc_example.c +@@ -137,86 +137,79 @@ void r5_rproc_remove(struct remoteproc *rproc) + } + } + +-void *r5_rproc_mmap(struct remoteproc *rproc, +- metal_phys_addr_t *pa, metal_phys_addr_t *da, +- size_t size, unsigned int attribute, +- struct metal_io_region **io) ++int r5_rproc_mmap(struct remoteproc *rproc, ++ metal_phys_addr_t *pa, metal_phys_addr_t *da, ++ void **va, size_t size, unsigned int attribute, ++ struct metal_io_region **io) + { + struct remoteproc_mem *mem; ++ struct metal_io_region *tmpio; + struct r5_rproc_priv *priv; +- metal_phys_addr_t lpa, lda; + + priv = rproc->priv; + +- if (!da || !pa) +- return NULL; + LPRINTF("%s: pa=0x%x, da=0x%x, size=0x%x, atrribute=0x%x\r\n", + __func__, *pa, *da, size, attribute); +- lda = *da; +- lpa = *pa; + if (!attribute) + attribute = NORM_SHARED_NCACHE | PRIV_RW_USER_RW; +- if (lda <= 0x40000) { ++ if (*da <= 0x40000) { + metal_phys_addr_t lda_end; + +- lda_end = lda + size; ++ lda_end = *da + size; + if (priv->cpu_id == NODE_RPU_0 || priv->cpu_id == NODE_RPU) { +- lpa = 0xFFE00000 + lda; +- if (lda < 0x10000) ++ *pa = 0xFFE00000 + *da; ++ if (*da < 0x10000) + XPm_RequestNode(NODE_TCM_0_A, + PM_CAP_ACCESS, 0, + REQUEST_ACK_BLOCKING); +- if (lda <= 0x20000 && lda_end >= 0x10000) ++ if (*da <= 0x20000 && lda_end >= 0x10000) + XPm_RequestNode(NODE_TCM_1_A, + PM_CAP_ACCESS, 0, + REQUEST_ACK_BLOCKING); +- if (lda <= 0x30000 && lda_end >= 0x20000) ++ if (*da <= 0x30000 && lda_end >= 0x20000) + XPm_RequestNode(NODE_TCM_0_B, + PM_CAP_ACCESS, 0, + REQUEST_ACK_BLOCKING); +- if (lda <= 0x40000 && lda_end >= 0x30000) ++ if (*da <= 0x40000 && lda_end >= 0x30000) + XPm_RequestNode(NODE_TCM_1_B, + PM_CAP_ACCESS, 0, + REQUEST_ACK_BLOCKING); + } else if (priv->cpu_id == NODE_RPU_1) { +- lpa = 0xFFE90000 + lda; +- if (lda < 0x10000) ++ *pa = 0xFFE90000 + *da; ++ if (*da < 0x10000) + XPm_RequestNode(NODE_TCM_1_A, + PM_CAP_ACCESS, 0, + REQUEST_ACK_BLOCKING); +- if (lda <= 0x30000 && lda_end >= 0x20000) ++ if (*da <= 0x30000 && lda_end >= 0x20000) + XPm_RequestNode(NODE_TCM_1_B, + PM_CAP_ACCESS, 0, + REQUEST_ACK_BLOCKING); + } else { + LPERROR("mmap failed: invalid cpu node: %d\r\n", + priv->cpu_id); +- return NULL; ++ return -RPROC_EINVAL; + } + } +- if (lpa == METAL_BAD_PHYS) +- lpa = lda; +- if (lpa == METAL_BAD_PHYS) +- return NULL; ++ if (*pa == METAL_BAD_PHYS) ++ *pa = *da; ++ if (*pa == METAL_BAD_PHYS) ++ return -RPROC_EINVAL; + mem = metal_allocate_memory(sizeof(*mem)); + if (!mem) +- return NULL; +- mem->pa = lpa; +- mem->da = lda; +- +- *io = metal_allocate_memory(sizeof(struct metal_io_region)); +- if (!*io) { ++ return -RPROC_ENOMEM; ++ tmpio = metal_allocate_memory(sizeof(struct metal_io_region)); ++ if (!tmpio) { + metal_free_memory(mem); +- return NULL; ++ return -RPROC_ENOMEM; + } +- metal_io_init(*io, (void *)mem->pa, &mem->pa, size, ++ remoteproc_init_mem(mem, NULL, *pa, *da, size, tmpio); ++ metal_io_init(tmpio, (void *)mem->pa, &mem->pa, size, + sizeof(metal_phys_addr_t)<<3, attribute, NULL); +- mem->io = *io; +- metal_list_add_tail(&rproc->mems, &mem->node); +- *pa = lpa; +- *da = lda; +- mem->size = size; +- return metal_io_phys_to_virt(*io, mem->pa); ++ remoteproc_add_mem(rproc, mem); ++ *va = metal_io_phys_to_virt(tmpio, mem->pa); ++ if (io) ++ *io = tmpio; ++ return 0; + } + + int r5_rproc_start(struct remoteproc *rproc) +diff --git a/apps/machine/zynq7/platform_info.c open-amp/apps/machine/zynq7/platform_info.c +index d753e0e..7885b31 100644 +--- a/apps/machine/zynq7/platform_info.c ++++ open-amp/apps/machine/zynq7/platform_info.c +@@ -108,16 +108,16 @@ platform_create_proc(int proc_index, int rsc_index) + */ + /* mmap resource table */ + pa = (metal_phys_addr_t)rsc_table; +- (void *)remoteproc_mmap(&rproc_inst, &pa, +- NULL, rsc_size, +- NORM_NONCACHE | STRONG_ORDERED, +- &rproc_inst.rsc_io); ++ remoteproc_mmap(&rproc_inst, &pa, ++ NULL, NULL, rsc_size, ++ NORM_NONCACHE | STRONG_ORDERED, ++ &rproc_inst.rsc_io); + /* mmap shared memory */ + pa = SHARED_MEM_PA; +- (void *)remoteproc_mmap(&rproc_inst, &pa, +- NULL, SHARED_MEM_SIZE, +- NORM_NONCACHE | STRONG_ORDERED, +- NULL); ++ remoteproc_mmap(&rproc_inst, &pa, ++ NULL, NULL, SHARED_MEM_SIZE, ++ NORM_NONCACHE | STRONG_ORDERED, ++ NULL); + + /* parse resource table to remoteproc */ + ret = remoteproc_set_rsc_table(&rproc_inst, rsc_table, rsc_size); +diff --git a/apps/machine/zynq7/zynq_a9_rproc.c open-amp/apps/machine/zynq7/zynq_a9_rproc.c +index f830749..ad7cd49 100644 +--- a/apps/machine/zynq7/zynq_a9_rproc.c ++++ open-amp/apps/machine/zynq7/zynq_a9_rproc.c +@@ -94,45 +94,43 @@ static void zynq_a9_proc_remove(struct remoteproc *rproc) + metal_device_close(dev); + } + +-static void * ++static int + zynq_a9_proc_mmap(struct remoteproc *rproc, metal_phys_addr_t *pa, +- metal_phys_addr_t *da, size_t size, +- unsigned int attribute, struct metal_io_region **io) ++ metal_phys_addr_t *da, void **va, size_t size, ++ unsigned int attribute, struct metal_io_region **io) + { + struct remoteproc_mem *mem; +- metal_phys_addr_t lpa, lda; + struct metal_io_region *tmpio; + +- lpa = *pa; +- lda = *da; +- +- if (lpa == METAL_BAD_PHYS && lda == METAL_BAD_PHYS) +- return NULL; +- if (lpa == METAL_BAD_PHYS) +- lpa = lda; +- if (lda == METAL_BAD_PHYS) +- lda = lpa; ++ /* va is the same as pa/da in this platform */ ++ if (*pa != METAL_BAD_PHYS) { ++ *da = *pa; ++ *va = (void *)*pa; ++ } else if (*da != METAL_BAD_PHYS) { ++ *pa = *da; ++ *va = (void *)*da; ++ } else if (*va) ++ *pa = *da = (metal_phys_addr_t)*va; ++ else ++ return -RPROC_EINVAL; + + if (!attribute) + attribute = NORM_NONCACHE | STRONG_ORDERED; + mem = metal_allocate_memory(sizeof(*mem)); + if (!mem) +- return NULL; ++ return -RPROC_ENOMEM; + tmpio = metal_allocate_memory(sizeof(*tmpio)); + if (!tmpio) { + metal_free_memory(mem); +- return NULL; ++ return -RPROC_ENOMEM; + } +- remoteproc_init_mem(mem, NULL, lpa, lda, size, tmpio); +- /* va is the same as pa in this platform */ +- metal_io_init(tmpio, (void *)lpa, &mem->pa, size, ++ remoteproc_init_mem(mem, NULL, *pa, *da, size, tmpio); ++ metal_io_init(tmpio, *va, &mem->pa, size, + sizeof(metal_phys_addr_t)<<3, attribute, NULL); + remoteproc_add_mem(rproc, mem); +- *pa = lpa; +- *da = lda; + if (io) + *io = tmpio; +- return metal_io_phys_to_virt(tmpio, mem->pa); ++ return 0; + } + + static int zynq_a9_proc_notify(struct remoteproc *rproc, uint32_t id) +diff --git a/apps/machine/zynqmp/platform_info.c open-amp/apps/machine/zynqmp/platform_info.c +index 3081ec9..17abcc5 100644 +--- a/apps/machine/zynqmp/platform_info.c ++++ open-amp/apps/machine/zynqmp/platform_info.c +@@ -84,7 +84,7 @@ static struct rpmsg_virtio_shm_pool shpool; + static struct remoteproc * + platform_create_proc(int proc_index, int rsc_index) + { +- void *rsc_table; ++ void *rsc_table = NULL; + int rsc_size; + int ret; + metal_phys_addr_t pa; +@@ -102,8 +102,8 @@ platform_create_proc(int proc_index, int rsc_index) + /* Mmap resource table */ + pa = RSC_MEM_PA; + printf("Calling mmap resource table.\r\n"); +- rsc_table = remoteproc_mmap(&rproc_inst, &pa, NULL, rsc_size, +- 0, NULL); ++ remoteproc_mmap(&rproc_inst, &pa, NULL, &rsc_table, rsc_size, ++ 0, NULL); + if (!rsc_table) { + fprintf(stderr, "ERROR: Failed to mmap resource table.\r\n"); + return NULL; +diff --git a/apps/machine/zynqmp/zynqmp_linux_r5_proc.c open-amp/apps/machine/zynqmp/zynqmp_linux_r5_proc.c +index 2e4df9d..0950d0b 100644 +--- a/apps/machine/zynqmp/zynqmp_linux_r5_proc.c ++++ open-amp/apps/machine/zynqmp/zynqmp_linux_r5_proc.c +@@ -143,38 +143,44 @@ static void zynqmp_linux_r5_proc_remove(struct remoteproc *rproc) + metal_device_close(prproc->shm_dev); + } + +-static void * ++static int + zynqmp_linux_r5_proc_mmap(struct remoteproc *rproc, metal_phys_addr_t *pa, +- metal_phys_addr_t *da, size_t size, +- unsigned int attribute, struct metal_io_region **io) ++ metal_phys_addr_t *da, void **va, size_t size, ++ unsigned int attribute, struct metal_io_region **io) + { + struct remoteproc_priv *prproc; +- metal_phys_addr_t lpa, lda; + struct metal_io_region *tmpio; + + (void)attribute; + (void)size; + if (!rproc) +- return NULL; ++ return -RPROC_EINVAL; + prproc = rproc->priv; +- lpa = *pa; +- lda = *da; + +- if (lpa == METAL_BAD_PHYS && lda == METAL_BAD_PHYS) +- return NULL; +- if (lpa == METAL_BAD_PHYS) +- lpa = lda; +- if (lda == METAL_BAD_PHYS) +- lda = lpa; + tmpio = prproc->shm_io; + if (!tmpio) +- return NULL; ++ return -RPROC_EINVAL; ++ ++ if (*pa != METAL_BAD_PHYS) { ++ *da = *pa; ++ *va = metal_io_phys_to_virt(tmpio, *pa); ++ if (!*va) ++ return -RPROC_EINVAL; ++ } else if (*da != METAL_BAD_PHYS) { ++ *pa = *da; ++ *va = metal_io_phys_to_virt(tmpio, *da); ++ if (!*va) ++ return -RPROC_EINVAL; ++ } else if (*va) { ++ *pa = *da = metal_io_virt_to_phys(tmpio, *va); ++ if (*pa == METAL_BAD_PHYS) ++ return -RPROC_EINVAL; ++ } else ++ return -RPROC_EINVAL; + +- *pa = lpa; +- *da = lda; + if (io) + *io = tmpio; +- return metal_io_phys_to_virt(tmpio, lpa); ++ return 0; + } + + static int zynqmp_linux_r5_proc_notify(struct remoteproc *rproc, uint32_t id) +diff --git a/apps/machine/zynqmp_r5/platform_info.c open-amp/apps/machine/zynqmp_r5/platform_info.c +index 96c03c9..a2f7d9d 100644 +--- a/apps/machine/zynqmp_r5/platform_info.c ++++ open-amp/apps/machine/zynqmp_r5/platform_info.c +@@ -114,16 +114,16 @@ platform_create_proc(int proc_index, int rsc_index) + */ + /* mmap resource table */ + pa = (metal_phys_addr_t)rsc_table; +- (void *)remoteproc_mmap(&rproc_inst, &pa, +- NULL, rsc_size, +- NORM_NSHARED_NCACHE|PRIV_RW_USER_RW, +- &rproc_inst.rsc_io); ++ remoteproc_mmap(&rproc_inst, &pa, ++ NULL, NULL, rsc_size, ++ NORM_NSHARED_NCACHE|PRIV_RW_USER_RW, ++ &rproc_inst.rsc_io); + /* mmap shared memory */ + pa = SHARED_MEM_PA; +- (void *)remoteproc_mmap(&rproc_inst, &pa, +- NULL, SHARED_MEM_SIZE, +- NORM_NSHARED_NCACHE|PRIV_RW_USER_RW, +- NULL); ++ remoteproc_mmap(&rproc_inst, &pa, ++ NULL, NULL, SHARED_MEM_SIZE, ++ NORM_NSHARED_NCACHE|PRIV_RW_USER_RW, ++ NULL); + + /* parse resource table to remoteproc */ + ret = remoteproc_set_rsc_table(&rproc_inst, rsc_table, rsc_size); +diff --git a/apps/machine/zynqmp_r5/zynqmp_r5_a53_rproc.c open-amp/apps/machine/zynqmp_r5/zynqmp_r5_a53_rproc.c +index ee25368..ef5299c 100644 +--- a/apps/machine/zynqmp_r5/zynqmp_r5_a53_rproc.c ++++ open-amp/apps/machine/zynqmp_r5/zynqmp_r5_a53_rproc.c +@@ -109,45 +109,43 @@ static void zynqmp_r5_a53_proc_remove(struct remoteproc *rproc) + } + } + +-static void * ++static int + zynqmp_r5_a53_proc_mmap(struct remoteproc *rproc, metal_phys_addr_t *pa, +- metal_phys_addr_t *da, size_t size, ++ metal_phys_addr_t *da, void **va, size_t size, + unsigned int attribute, struct metal_io_region **io) + { + struct remoteproc_mem *mem; +- metal_phys_addr_t lpa, lda; + struct metal_io_region *tmpio; + +- lpa = *pa; +- lda = *da; +- +- if (lpa == METAL_BAD_PHYS && lda == METAL_BAD_PHYS) +- return NULL; +- if (lpa == METAL_BAD_PHYS) +- lpa = lda; +- if (lda == METAL_BAD_PHYS) +- lda = lpa; ++ /* va is the same as pa/da in this platform */ ++ if (*pa != METAL_BAD_PHYS) { ++ *da = *pa; ++ *va = (void *)*pa; ++ } else if (*da != METAL_BAD_PHYS) { ++ *pa = *da; ++ *va = (void *)*da; ++ } else if (*va) ++ *pa = *da = (metal_phys_addr_t)*va; ++ else ++ return -RPROC_EINVAL; + + if (!attribute) + attribute = NORM_SHARED_NCACHE | PRIV_RW_USER_RW; + mem = metal_allocate_memory(sizeof(*mem)); + if (!mem) +- return NULL; ++ return -RPROC_ENOMEM; + tmpio = metal_allocate_memory(sizeof(*tmpio)); + if (!tmpio) { + metal_free_memory(mem); +- return NULL; ++ return -RPROC_ENOMEM; + } +- remoteproc_init_mem(mem, NULL, lpa, lda, size, tmpio); +- /* va is the same as pa in this platform */ +- metal_io_init(tmpio, (void *)lpa, &mem->pa, size, ++ remoteproc_init_mem(mem, NULL, *pa, *da, size, tmpio); ++ metal_io_init(tmpio, *va, &mem->pa, size, + sizeof(metal_phys_addr_t)<<3, attribute, NULL); + remoteproc_add_mem(rproc, mem); +- *pa = lpa; +- *da = lda; + if (io) + *io = tmpio; +- return metal_io_phys_to_virt(tmpio, mem->pa); ++ return 0; + } + + static int zynqmp_r5_a53_proc_notify(struct remoteproc *rproc, uint32_t id) +diff --git a/apps/system/linux/machine/generic/platform_info.c open-amp/apps/system/linux/machine/generic/platform_info.c +index 5743c5c..66d15c1 100644 +--- a/apps/system/linux/machine/generic/platform_info.c ++++ open-amp/apps/system/linux/machine/generic/platform_info.c +@@ -319,39 +319,43 @@ static void linux_proc_remove(struct remoteproc *rproc) + } + } + +-static void * ++static int + linux_proc_mmap(struct remoteproc *rproc, metal_phys_addr_t *pa, +- metal_phys_addr_t *da, size_t size, ++ metal_phys_addr_t *da, void **va, size_t size, + unsigned int attribute, struct metal_io_region **io) + { + struct remoteproc_mem *mem; + struct remoteproc_priv *prproc; +- metal_phys_addr_t lpa, lda; +- void *va; + + (void)attribute; + (void)size; +- lpa = *pa; +- lda = *da; +- +- if (lpa == METAL_BAD_PHYS && lda == METAL_BAD_PHYS) +- return NULL; +- if (lpa == METAL_BAD_PHYS) +- lpa = lda; +- if (lda == METAL_BAD_PHYS) +- lda = lpa; + + if (!rproc) +- return NULL; ++ return -RPROC_EINVAL; + prproc = rproc->priv; + mem = &prproc->shm; +- va = metal_io_phys_to_virt(mem->io, lpa); +- if (va) { +- if (io) +- *io = mem->io; +- metal_list_add_tail(&rproc->mems, &mem->node); +- } +- return va; ++ ++ if (*pa != METAL_BAD_PHYS) { ++ *da = *pa; ++ *va = metal_io_phys_to_virt(mem->io, *pa); ++ if (!*va) ++ return -RPROC_EINVAL; ++ } else if (*da != METAL_BAD_PHYS) { ++ *pa = *da; ++ *va = metal_io_phys_to_virt(mem->io, *da); ++ if (!*va) ++ return -RPROC_EINVAL; ++ } else if (*va) { ++ *pa = *da = metal_io_virt_to_phys(mem->io, *va); ++ if (*pa == METAL_BAD_PHYS) ++ return -RPROC_EINVAL; ++ } else ++ return -RPROC_EINVAL; ++ ++ remoteproc_add_mem(rproc, mem); ++ if (io) ++ *io = mem->io; ++ return 0; + } + + static int linux_proc_notify(struct remoteproc *rproc, uint32_t id) +@@ -420,7 +424,7 @@ static struct remoteproc * + platform_create_proc(int proc_index, int rsc_index) + { + struct remoteproc_priv *prproc; +- void *rsc_table, *rsc_table_shm; ++ void *rsc_table, *rsc_table_shm = NULL; + int rsc_size; + int ret; + metal_phys_addr_t pa; +@@ -449,8 +453,8 @@ platform_create_proc(int proc_index, int rsc_index) + + /* Mmap resource table */ + pa = RSC_MEM_PA; +- rsc_table_shm = remoteproc_mmap(&rproc_inst, &pa, NULL, rsc_size, +- 0, &rproc_inst.rsc_io); ++ remoteproc_mmap(&rproc_inst, &pa, NULL, &rsc_table_shm, rsc_size, ++ 0, &rproc_inst.rsc_io); + + /* parse resource table to remoteproc */ + ret = remoteproc_set_rsc_table(&rproc_inst, rsc_table_shm, rsc_size); +diff --git a/lib/include/openamp/remoteproc.h open-amp/lib/include/openamp/remoteproc.h +index a83aa12..b34cb1a 100644 +--- a/lib/include/openamp/remoteproc.h ++++ open-amp/lib/include/openamp/remoteproc.h +@@ -400,10 +400,10 @@ struct remoteproc_ops { + struct remoteproc *(*init)(struct remoteproc *rproc, + struct remoteproc_ops *ops, void *arg); + void (*remove)(struct remoteproc *rproc); +- void *(*mmap)(struct remoteproc *rproc, +- metal_phys_addr_t *pa, metal_phys_addr_t *da, +- size_t size, unsigned int attribute, +- struct metal_io_region **io); ++ int (*mmap)(struct remoteproc *rproc, ++ metal_phys_addr_t *pa, metal_phys_addr_t *da, ++ void **va, size_t size, unsigned int attribute, ++ struct metal_io_region **io); + int (*handle_rsc)(struct remoteproc *rproc, void *rsc, size_t len); + int (*config)(struct remoteproc *rproc, void *data); + int (*start)(struct remoteproc *rproc); +@@ -606,16 +606,17 @@ remoteproc_get_io_with_va(struct remoteproc *rproc, + * @rproc - pointer to the remote processor + * @pa - physical address pointer + * @da - device address pointer ++ * @va - virtual address pointer + * @size - size of the memory + * @attribute - memory attribute + * @io - pointer to the I/O region + * +- * returns pointer to the memory ++ * returns 0 for success and negative value for errors + */ +-void *remoteproc_mmap(struct remoteproc *rproc, +- metal_phys_addr_t *pa, metal_phys_addr_t *da, +- size_t size, unsigned int attribute, +- struct metal_io_region **io); ++int remoteproc_mmap(struct remoteproc *rproc, ++ metal_phys_addr_t *pa, metal_phys_addr_t *da, ++ void **va, size_t size, unsigned int attribute, ++ struct metal_io_region **io); + + /** + * remoteproc_set_rsc_table +diff --git a/lib/remoteproc/remoteproc.c open-amp/lib/remoteproc/remoteproc.c +index 057edc6..27fcdb4 100644 +--- a/lib/remoteproc/remoteproc.c ++++ open-amp/lib/remoteproc/remoteproc.c +@@ -295,13 +295,14 @@ struct metal_io_region * + remoteproc_get_io_with_pa(struct remoteproc *rproc, + metal_phys_addr_t pa) + { +- struct remoteproc_mem *mem; ++ struct metal_io_region *io; ++ int ret; + +- mem = remoteproc_get_mem(rproc, NULL, pa, METAL_BAD_PHYS, NULL, 0); +- if (mem) +- return mem->io; +- else ++ ret = remoteproc_mmap(rproc, &pa, NULL, NULL, 0, 0, &io); ++ if (ret < 0) + return NULL; ++ ++ return io; + } + + struct metal_io_region * +@@ -309,48 +310,44 @@ remoteproc_get_io_with_da(struct remoteproc *rproc, + metal_phys_addr_t da, + unsigned long *offset) + { +- struct remoteproc_mem *mem; +- +- mem = remoteproc_get_mem(rproc, NULL, METAL_BAD_PHYS, da, NULL, 0); +- if (mem) { +- struct metal_io_region *io; +- metal_phys_addr_t pa; ++ struct metal_io_region *io; ++ metal_phys_addr_t pa = METAL_BAD_PHYS; ++ int ret; + +- io = mem->io; +- pa = remoteproc_datopa(mem, da); +- *offset = metal_io_phys_to_offset(io, pa); +- return io; +- } else { ++ ret = remoteproc_mmap(rproc, &pa, &da, NULL, 0, 0, &io); ++ if (ret < 0) + return NULL; +- } ++ ++ *offset = metal_io_phys_to_offset(io, pa); ++ return io; + } + + struct metal_io_region * + remoteproc_get_io_with_va(struct remoteproc *rproc, void *va) + { +- struct remoteproc_mem *mem; ++ struct metal_io_region *io; ++ int ret; + +- mem = remoteproc_get_mem(rproc, NULL, METAL_BAD_PHYS, METAL_BAD_PHYS, +- va, 0); +- if (mem) +- return mem->io; +- else ++ ret = remoteproc_mmap(rproc, NULL, NULL, &va, 0, 0, &io); ++ if (ret < 0) + return NULL; ++ ++ return io; + } + +-void *remoteproc_mmap(struct remoteproc *rproc, +- metal_phys_addr_t *pa, metal_phys_addr_t *da, +- size_t size, unsigned int attribute, +- struct metal_io_region **io) ++int remoteproc_mmap(struct remoteproc *rproc, ++ metal_phys_addr_t *pa, metal_phys_addr_t *da, ++ void **va, size_t size, unsigned int attribute, ++ struct metal_io_region **io) + { +- void *va = NULL; ++ void *lva = NULL; + metal_phys_addr_t lpa, lda; + struct remoteproc_mem *mem; + + if (!rproc) +- return NULL; +- else if (!pa && !da) +- return NULL; ++ return -RPROC_EINVAL; ++ else if (!pa && !da && !va) ++ return -RPROC_EINVAL; + if (pa) + lpa = *pa; + else +@@ -359,24 +356,40 @@ void *remoteproc_mmap(struct remoteproc *rproc, + lda = *da; + else + lda = METAL_BAD_PHYS; +- mem = remoteproc_get_mem(rproc, NULL, lpa, lda, NULL, size); ++ if (va) ++ lva = *va; ++ mem = remoteproc_get_mem(rproc, NULL, lpa, lda, lva, size); + if (mem) { +- if (lpa != METAL_BAD_PHYS) ++ if (lpa != METAL_BAD_PHYS) { + lda = remoteproc_patoda(mem, lpa); +- else if (lda != METAL_BAD_PHYS) ++ lva = metal_io_phys_to_virt(mem->io, lpa); ++ } else if (lda != METAL_BAD_PHYS) { + lpa = remoteproc_datopa(mem, lda); ++ lva = metal_io_phys_to_virt(mem->io, lpa); ++ } else if (lva != NULL) { ++ lpa = metal_io_virt_to_phys(mem->io, lva); ++ lda = remoteproc_patoda(mem, lpa); ++ } + if (io) + *io = mem->io; +- va = metal_io_phys_to_virt(mem->io, lpa); +- } else if (rproc->ops->mmap) { +- va = rproc->ops->mmap(rproc, &lpa, &lda, size, attribute, io); ++ } else { ++ int ret = -RPROC_EINVAL; ++ ++ if (rproc->ops->mmap) ++ ret = rproc->ops->mmap(rproc, &lpa, &lda, &lva, size, attribute, io); ++ ++ if (ret < 0) ++ return ret; + } + + if (pa) + *pa = lpa; + if (da) + *da = lda; +- return va; ++ if (va) ++ *va = lva; ++ ++ return 0; + } + + int remoteproc_load(struct remoteproc *rproc, const char *path, +@@ -529,8 +542,8 @@ int remoteproc_load(struct remoteproc *rproc, const char *path, + img_data = NULL; + /* get the I/O region from remoteproc */ + pa = METAL_BAD_PHYS; +- (void)remoteproc_mmap(rproc, &pa, &da, nmemsize, 0, &io); +- if (pa == METAL_BAD_PHYS || io == NULL) { ++ remoteproc_mmap(rproc, &pa, &da, NULL, nmemsize, 0, &io); ++ if (pa == METAL_BAD_PHYS || !io) { + metal_log(METAL_LOG_ERROR, + "load failed, no mapping for 0x%llx.\r\n", + da); +@@ -599,8 +612,9 @@ int remoteproc_load(struct remoteproc *rproc, const char *path, + + metal_log(METAL_LOG_DEBUG, + "%s, update resource table\r\n", __func__); +- rsc_table = remoteproc_mmap(rproc, NULL, &rsc_da, +- rsc_size, 0, &io); ++ rsc_table = NULL; ++ remoteproc_mmap(rproc, NULL, &rsc_da, ++ &rsc_table, rsc_size, 0, &io); + if (rsc_table) { + size_t rsc_io_offset; + +@@ -759,8 +773,8 @@ int remoteproc_load_noblock(struct remoteproc *rproc, + if (da != RPROC_LOAD_ANYADDR) { + /* get the I/O region from remoteproc */ + *pa = METAL_BAD_PHYS; +- (void)remoteproc_mmap(rproc, pa, &da, *nmlen, 0, io); +- if (*pa == METAL_BAD_PHYS || io == NULL) { ++ remoteproc_mmap(rproc, pa, &da, NULL, *nmlen, 0, io); ++ if (*pa == METAL_BAD_PHYS || !io) { + metal_log(METAL_LOG_ERROR, + "load failed, no mapping for 0x%llx.\r\n", + da); +@@ -784,9 +798,9 @@ int remoteproc_load_noblock(struct remoteproc *rproc, + ret = -RPROC_ENOMEM; + goto error1; + } +- rsc_table = remoteproc_mmap(rproc, NULL, &rsc_da, +- rsc_size, 0, io); +- if (*io == NULL) { ++ remoteproc_mmap(rproc, NULL, &rsc_da, ++ &rsc_table, rsc_size, 0, io); ++ if (!*io) { + metal_log(METAL_LOG_ERROR, + "load failed: failed to mmap rsc\r\n"); + metal_free_memory(lrsc_table); +@@ -923,7 +937,7 @@ remoteproc_create_virtio(struct remoteproc *rproc, + metal_phys_addr_t da; + unsigned int num_descs, align; + struct metal_io_region *io; +- void *va; ++ void *va = NULL; + size_t size; + int ret; + +@@ -933,7 +947,7 @@ remoteproc_create_virtio(struct remoteproc *rproc, + num_descs = vring_rsc->num; + align = vring_rsc->align; + size = vring_size(num_descs, align); +- va = remoteproc_mmap(rproc, NULL, &da, size, 0, &io); ++ remoteproc_mmap(rproc, NULL, &da, &va, size, 0, &io); + if (!va) + goto err1; + ret = rproc_virtio_init_vring(vdev, i, notifyid, +diff --git a/lib/remoteproc/rsc_table_parser.c open-amp/lib/remoteproc/rsc_table_parser.c +index 184a463..816a0ee 100644 +--- a/lib/remoteproc/rsc_table_parser.c ++++ open-amp/lib/remoteproc/rsc_table_parser.c +@@ -109,7 +109,7 @@ int handle_carve_out_rsc(struct remoteproc *rproc, void *rsc) + da = carve_rsc->da; + size = carve_rsc->len; + attribute = carve_rsc->flags; +- if (remoteproc_mmap(rproc, &pa, &da, size, attribute, NULL)) ++ if (remoteproc_mmap(rproc, &pa, &da, NULL, size, attribute, NULL)) + return 0; + else + return -RPROC_EINVAL; +-- +2.17.1 + diff --git a/openamp/0007-rpmsg-bring-back-zero-copy-transfer.patch b/openamp/0007-rpmsg-bring-back-zero-copy-transfer.patch new file mode 100644 index 0000000000..5a65e52392 --- /dev/null +++ b/openamp/0007-rpmsg-bring-back-zero-copy-transfer.patch @@ -0,0 +1,470 @@ +From 4224f5f028aec8ebc13e1e203cbae3127b07605e Mon Sep 17 00:00:00 2001 +From: anchao +Date: Mon, 10 Dec 2018 19:39:01 +0800 +Subject: [PATCH 07/10] rpmsg: bring back zero copy transfer + +Commit-id: +b16ca55 Adding RPMsg Extension layer implementing zero-copy send and receive. + +Signed-off-by: anchao +--- + lib/include/openamp/rpmsg.h | 178 ++++++++++++++++++++++++++++++++++++ + lib/rpmsg/rpmsg.c | 58 ++++++++++++ + lib/rpmsg/rpmsg_internal.h | 3 + + lib/rpmsg/rpmsg_virtio.c | 130 +++++++++++++++++++++++++- + 4 files changed, 367 insertions(+), 2 deletions(-) + +diff --git a/lib/include/openamp/rpmsg.h open-amp/lib/include/openamp/rpmsg.h +index 1279ea2..0b46ee1 100644 +--- a/lib/include/openamp/rpmsg.h ++++ open-amp/lib/include/openamp/rpmsg.h +@@ -89,9 +89,20 @@ struct rpmsg_endpoint { + + /** + * struct rpmsg_device_ops - RPMsg device operations ++ * @hold_rx_buffer: hold RPMsg RX buffer ++ * @release_rx_buffer: release RPMsg RX buffer ++ * @get_tx_payload_buffer: get RPMsg TX buffer ++ * @send_offchannel_nocopy: send RPMsg data without copy + * @send_offchannel_raw: send RPMsg data + */ + struct rpmsg_device_ops { ++ void (*hold_rx_buffer)(struct rpmsg_device *rdev, void *rxbuf); ++ void (*release_rx_buffer)(struct rpmsg_device *rdev, void *rxbuf); ++ void *(*get_tx_payload_buffer)(struct rpmsg_device *rdev, ++ uint32_t *len, int wait); ++ int (*send_offchannel_nocopy)(struct rpmsg_device *rdev, ++ uint32_t src, uint32_t dst, ++ const void *data, int len); + int (*send_offchannel_raw)(struct rpmsg_device *rdev, + uint32_t src, uint32_t dst, + const void *data, int size, int wait); +@@ -294,6 +305,173 @@ static inline int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, + return rpmsg_send_offchannel_raw(ept, src, dst, data, len, false); + } + ++/** ++ * @brief Holds the rx buffer for usage outside the receive callback. ++ * ++ * Calling this function prevents the RPMsg receive buffer from being released ++ * back to the pool of shmem buffers. This API can only be called at rx ++ * callback context (rpmsg_rx_cb_t). With this API, the application doesn't ++ * need to copy the message in rx callback. Instead, the rx buffer base address ++ * is saved in application context and further processed in application ++ * process. After the message is processed, the application can release the rx ++ * buffer for future reuse in vring by calling the rpmsg_release_rx_buffer() ++ * function. ++ * ++ * @param: ept The rpmsg endpoint ++ * @param: rxbuf RX buffer with message payload ++ * ++ * @see rpmsg_release_rx_buffer ++ */ ++void rpmsg_hold_rx_buffer(struct rpmsg_endpoint *ept, void *rxbuf); ++ ++/** ++ * @brief Releases the rx buffer for future reuse in vring. ++ * ++ * This API can be called at process context when the message in rx buffer is ++ * processed. ++ * ++ * @ept: the rpmsg endpoint ++ * @rxbuf: rx buffer with message payload ++ * ++ * @see rpmsg_hold_rx_buffer ++ */ ++void rpmsg_release_rx_buffer(struct rpmsg_endpoint *ept, void *rxbuf); ++ ++/** ++ * @brief Gets the tx buffer for message payload. ++ * ++ * This API can only be called at process context to get the tx buffer in vring. ++ * By this way, the application can directly put its message into the vring tx ++ * buffer without copy from an application buffer. ++ * It is the application responsibility to correctly fill the allocated tx ++ * buffer by data and passing correct parameters to the rpmsg_send_nocopy() or ++ * rpmsg_sendto_nocopy() function to perform data no-copy-send mechanism. ++ * ++ * @ept: Pointer to rpmsg endpoint ++ * @len: Pointer to store tx buffer size ++ * @wait: Boolean, wait or not for buffer to become available ++ * ++ * @return The tx buffer address on success and NULL on failure ++ * ++ * @see rpmsg_send_offchannel_nocopy ++ * @see rpmsg_sendto_nocopy ++ * @see rpmsg_send_nocopy ++ */ ++void *rpmsg_get_tx_payload_buffer(struct rpmsg_endpoint *ept, ++ uint32_t *len, int wait); ++ ++/** ++ * rpmsg_send_offchannel_nocopy() - send a message in tx buffer reserved by ++ * rpmsg_get_tx_payload_buffer() across to the remote processor. ++ * ++ * This function sends buf 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. ++ * The application has to take the responsibility for: ++ * 1. tx buffer reserved (rpmsg_get_tx_payload_buffer() ) ++ * 2. filling the data to be sent into the pre-allocated tx buffer ++ * 3. not exceeding the buffer size when filling the data ++ * 4. data cache coherency ++ * ++ * After the rpmsg_send_offchannel_nocopy() function is issued the tx buffer is ++ * no more owned by the sending task and must not be touched anymore unless the ++ * rpmsg_send_offchannel_nocopy() function fails and returns an error. In that ++ * case the application should try to re-issue the rpmsg_send_offchannel_nocopy() ++ * again. ++ * ++ * @ept: The rpmsg endpoint ++ * @src: The rpmsg endpoint local address ++ * @dst: The rpmsg endpoint remote address ++ * @data: TX buffer with message filled ++ * @len: Length of payload ++ * ++ * @return number of bytes it has sent or negative error value on failure. ++ * ++ * @see rpmsg_get_tx_payload_buffer ++ * @see rpmsg_sendto_nocopy ++ * @see rpmsg_send_nocopy ++ */ ++int rpmsg_send_offchannel_nocopy(struct rpmsg_endpoint *ept, uint32_t src, ++ uint32_t dst, const void *data, int len); ++ ++/** ++ * @brief Sends a message in tx buffer allocated by rpmsg_get_tx_payload_buffer() ++ * across to the remote processor, specify dst. ++ * ++ * This function sends buf 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 source address. ++ * The application has to take the responsibility for: ++ * 1. tx buffer allocation (rpmsg_get_tx_payload_buffer() ) ++ * 2. filling the data to be sent into the pre-allocated tx buffer ++ * 3. not exceeding the buffer size when filling the data ++ * 4. data cache coherency ++ * ++ * After the rpmsg_sendto_nocopy() function is issued the tx buffer is no more ++ * owned by the sending task and must not be touched anymore unless the ++ * rpmsg_sendto_nocopy() function fails and returns an error. In that case the ++ * application should try to re-issue the rpmsg_sendto_nocopy() again. ++ * ++ * @ept: The rpmsg endpoint ++ * @data: TX buffer with message filled ++ * @len: Length of payload ++ * @dst: Destination address ++ * ++ * @return number of bytes it has sent or negative error value on failure. ++ * ++ * @see rpmsg_get_tx_payload_buffer ++ * @see rpmsg_send_offchannel_nocopy ++ * @see rpmsg_send_nocopy ++ */ ++static inline int rpmsg_sendto_nocopy(struct rpmsg_endpoint *ept, ++ const void *data, int len, uint32_t dst) ++{ ++ return rpmsg_send_offchannel_nocopy(ept, ept->addr, dst, data, len); ++} ++ ++/** ++ * rpmsg_send_nocopy() - send a message in tx buffer reserved by ++ * rpmsg_get_tx_payload_buffer() across to the remote processor. ++ * ++ * This function sends buf 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 source and destination addresses. ++ * The application has to take the responsibility for: ++ * 1. tx buffer reserved (rpmsg_get_tx_payload_buffer() ) ++ * 2. filling the data to be sent into the pre-allocated tx buffer ++ * 3. not exceeding the buffer size when filling the data ++ * 4. data cache coherency ++ * ++ * After the rpmsg_send_nocopy() function is issued the tx buffer is no more ++ * owned by the sending task and must not be touched anymore unless the ++ * rpmsg_send_nocopy() function fails and returns an error. In that case the ++ * application should try to re-issue the rpmsg_send_nocopy() again. ++ * ++ * @ept: The rpmsg endpoint ++ * @data: TX buffer with message filled ++ * @len: Length of payload ++ * ++ * @return number of bytes it has sent or negative error value on failure. ++ * ++ * @see rpmsg_get_tx_payload_buffer ++ * @see rpmsg_send_offchannel_nocopy ++ * @see rpmsg_sendto_nocopy ++ */ ++static inline int rpmsg_send_nocopy(struct rpmsg_endpoint *ept, const void *data, int len) ++{ ++ int tc = 0; ++ ++ for (; tc < RPMSG_TICK_COUNT; tc += RPMSG_TICKS_PER_INTERVAL) { ++ if (is_rpmsg_ept_ready(ept)) ++ return rpmsg_send_offchannel_nocopy(ept, ept->addr, ++ ept->dest_addr, data, len); ++ metal_sleep_usec(RPMSG_TICKS_PER_INTERVAL); ++ } ++ ++ return RPMSG_ERR_ADDR; ++} ++ + /** + * rpmsg_init_ept - initialize rpmsg endpoint + * +diff --git a/lib/rpmsg/rpmsg.c open-amp/lib/rpmsg/rpmsg.c +index 9da38a1..0a8de1b 100644 +--- a/lib/rpmsg/rpmsg.c ++++ open-amp/lib/rpmsg/rpmsg.c +@@ -144,6 +144,64 @@ int rpmsg_send_ns_message(struct rpmsg_endpoint *ept, unsigned long flags) + return RPMSG_SUCCESS; + } + ++void rpmsg_hold_rx_buffer(struct rpmsg_endpoint *ept, void *rxbuf) ++{ ++ struct rpmsg_device *rdev; ++ ++ if (!ept || !ept->rdev || !rxbuf) ++ return; ++ ++ rdev = ept->rdev; ++ ++ if (rdev->ops.hold_rx_buffer) ++ rdev->ops.hold_rx_buffer(rdev, rxbuf); ++} ++ ++void rpmsg_release_rx_buffer(struct rpmsg_endpoint *ept, void *rxbuf) ++{ ++ struct rpmsg_device *rdev; ++ ++ if (!ept || !ept->rdev || !rxbuf) ++ return; ++ ++ rdev = ept->rdev; ++ ++ if (rdev->ops.release_rx_buffer) ++ rdev->ops.release_rx_buffer(rdev, rxbuf); ++} ++ ++void *rpmsg_get_tx_payload_buffer(struct rpmsg_endpoint *ept, ++ uint32_t *len, int wait) ++{ ++ struct rpmsg_device *rdev; ++ ++ if (!ept || !ept->rdev || !len) ++ return NULL; ++ ++ rdev = ept->rdev; ++ ++ if (rdev->ops.get_tx_payload_buffer) ++ return rdev->ops.get_tx_payload_buffer(rdev, len, wait); ++ ++ return NULL; ++} ++ ++int rpmsg_send_offchannel_nocopy(struct rpmsg_endpoint *ept, uint32_t src, ++ uint32_t dst, const void *data, int len) ++{ ++ struct rpmsg_device *rdev; ++ ++ if (!ept || !ept->rdev || !data || !dst || dst == RPMSG_ADDR_ANY) ++ return RPMSG_ERR_PARAM; ++ ++ rdev = ept->rdev; ++ ++ if (rdev->ops.send_offchannel_nocopy) ++ return rdev->ops.send_offchannel_nocopy(rdev, src, dst, data, len); ++ ++ return RPMSG_ERR_PARAM; ++} ++ + struct rpmsg_endpoint *rpmsg_get_endpoint(struct rpmsg_device *rdev, + const char *name, uint32_t addr, + uint32_t dest_addr) +diff --git a/lib/rpmsg/rpmsg_internal.h open-amp/lib/rpmsg/rpmsg_internal.h +index 9c46970..3db6b24 100644 +--- a/lib/rpmsg/rpmsg_internal.h ++++ open-amp/lib/rpmsg/rpmsg_internal.h +@@ -35,6 +35,9 @@ extern "C" { + } while (0) + #endif + ++#define RPMSG_BUF_HELD (1U << 31) /* Flag to suggest to hold the buffer */ ++ ++#define RPMSG_LOCATE_HDR(p) (struct rpmsg_hdr *)((char *)(p) - sizeof(struct rpmsg_hdr)) + #define RPMSG_LOCATE_DATA(p) ((unsigned char *)(p) + sizeof(struct rpmsg_hdr)) + /** + * enum rpmsg_ns_flags - dynamic name service announcement flags +diff --git a/lib/rpmsg/rpmsg_virtio.c open-amp/lib/rpmsg/rpmsg_virtio.c +index 17f2998..a525066 100644 +--- a/lib/rpmsg/rpmsg_virtio.c ++++ open-amp/lib/rpmsg/rpmsg_virtio.c +@@ -140,6 +140,7 @@ static void *rpmsg_virtio_get_tx_buffer(struct rpmsg_virtio_device *rvdev, + data = rpmsg_virtio_shm_pool_get_buffer(rvdev->shpool, + RPMSG_BUFFER_SIZE); + *len = RPMSG_BUFFER_SIZE; ++ *idx = 0; + } + } + #endif /*!VIRTIO_SLAVE_ONLY*/ +@@ -253,6 +254,118 @@ static int _rpmsg_virtio_get_buffer_size(struct rpmsg_virtio_device *rvdev) + return length; + } + ++static void rpmsg_virtio_hold_rx_buffer(struct rpmsg_device *rdev, void *rxbuf) ++{ ++ struct rpmsg_hdr *rp_hdr; ++ ++ rp_hdr = RPMSG_LOCATE_HDR(rxbuf); ++ ++ /* Set held status to keep buffer */ ++ rp_hdr->reserved = RPMSG_BUF_HELD; ++} ++ ++static void rpmsg_virtio_release_rx_buffer(struct rpmsg_device *rdev, void *rxbuf) ++{ ++ struct rpmsg_virtio_device *rvdev; ++ struct rpmsg_hdr *rp_hdr; ++ uint16_t idx; ++ uint32_t len; ++ ++ rvdev = metal_container_of(rdev, struct rpmsg_virtio_device, rdev); ++ rp_hdr = RPMSG_LOCATE_HDR(rxbuf); ++ /* The reserved field contains buffer index */ ++ idx = rp_hdr->reserved; ++ ++ metal_mutex_acquire(&rdev->lock); ++ /* Return buffer on virtqueue. */ ++ len = virtqueue_get_buffer_length(rvdev->rvq, idx); ++ rpmsg_virtio_return_buffer(rvdev, rp_hdr, len, idx); ++ metal_mutex_release(&rdev->lock); ++} ++ ++static void *rpmsg_virtio_get_tx_payload_buffer(struct rpmsg_device *rdev, ++ uint32_t *len, int wait) ++{ ++ struct rpmsg_virtio_device *rvdev; ++ struct rpmsg_hdr *rp_hdr; ++ uint16_t idx; ++ int tick_count; ++ ++ /* Get the associated remote device for channel. */ ++ rvdev = metal_container_of(rdev, struct rpmsg_virtio_device, rdev); ++ ++ if (wait) ++ tick_count = RPMSG_TICK_COUNT / RPMSG_TICKS_PER_INTERVAL; ++ else ++ tick_count = 0; ++ ++ while (1) { ++ /* Lock the device to enable exclusive access to virtqueues */ ++ metal_mutex_acquire(&rdev->lock); ++ rp_hdr = rpmsg_virtio_get_tx_buffer(rvdev, len, &idx); ++ metal_mutex_release(&rdev->lock); ++ if (rp_hdr || !tick_count) ++ break; ++ metal_sleep_usec(RPMSG_TICKS_PER_INTERVAL); ++ tick_count--; ++ } ++ ++ if (!rp_hdr) ++ return NULL; ++ ++ /* Store the index into the reserved field to be used when sending */ ++ rp_hdr->reserved = idx; ++ ++ /* Actual data buffer size is vring buffer size minus rpmsg header length */ ++ *len -= sizeof(struct rpmsg_hdr); ++ return RPMSG_LOCATE_DATA(rp_hdr); ++} ++ ++static int rpmsg_virtio_send_offchannel_nocopy(struct rpmsg_device *rdev, ++ uint32_t src, uint32_t dst, ++ const void *data, int len) ++{ ++ struct rpmsg_virtio_device *rvdev; ++ struct rpmsg_hdr rp_hdr; ++ struct rpmsg_hdr *hdr; ++ uint16_t idx; ++ int status; ++ struct metal_io_region *io; ++ ++ /* Get the associated remote device for channel. */ ++ rvdev = metal_container_of(rdev, struct rpmsg_virtio_device, rdev); ++ ++ hdr = RPMSG_LOCATE_HDR(data); ++ /* The reserved field contains buffer index */ ++ idx = hdr->reserved; ++ ++ /* Initialize RPMSG header. */ ++ rp_hdr.dst = dst; ++ rp_hdr.src = src; ++ rp_hdr.len = len; ++ rp_hdr.reserved = 0; ++ rp_hdr.flags = 0; ++ ++ /* Copy data to rpmsg buffer. */ ++ io = rvdev->shbuf_io; ++ status = metal_io_block_write(io, metal_io_virt_to_offset(io, hdr), ++ &rp_hdr, sizeof(rp_hdr)); ++ RPMSG_ASSERT(status == sizeof(rp_hdr), "failed to write header\r\n"); ++ ++ metal_mutex_acquire(&rdev->lock); ++ ++ /* Enqueue buffer on virtqueue. */ ++ len = virtqueue_get_buffer_length(rvdev->svq, idx); ++ status = rpmsg_virtio_enqueue_buffer(rvdev, hdr, len, idx); ++ RPMSG_ASSERT(status == VQUEUE_SUCCESS, "failed to enqueue buffer\r\n"); ++ /* Let the other side know that there is a job to process. */ ++ virtqueue_kick(rvdev->svq); ++ ++ metal_mutex_release(&rdev->lock); ++ ++ return len; ++} ++ + /** + * This function sends rpmsg "message" to remote device. + * +@@ -389,6 +502,8 @@ static void rpmsg_virtio_rx_callback(struct virtqueue *vq) + metal_mutex_release(&rdev->lock); + + while (rp_hdr) { ++ rp_hdr->reserved = 0; ++ + /* Get the channel node from the remote device channels list. */ + metal_mutex_acquire(&rdev->lock); + ept = rpmsg_get_ept_from_addr(rdev, rp_hdr->dst); +@@ -411,8 +526,15 @@ static void rpmsg_virtio_rx_callback(struct virtqueue *vq) + + metal_mutex_acquire(&rdev->lock); + +- /* Return used buffers. */ +- rpmsg_virtio_return_buffer(rvdev, rp_hdr, len, idx); ++ /* Check whether callback wants to hold buffer */ ++ if (rp_hdr->reserved & RPMSG_BUF_HELD) { ++ /* 'rp_hdr->reserved' field is now used as storage for ++ * 'idx' to release buffer later */ ++ rp_hdr->reserved = idx; ++ } else { ++ /* Return used buffers. */ ++ rpmsg_virtio_return_buffer(rvdev, rp_hdr, len, idx); ++ } + + rp_hdr = rpmsg_virtio_get_rx_buffer(rvdev, &len, &idx); + if (rp_hdr == NULL) { +@@ -522,6 +644,10 @@ int rpmsg_init_vdev(struct rpmsg_virtio_device *rvdev, + rvdev->vdev = vdev; + rdev->ns_bind_cb = ns_bind_cb; + vdev->priv = rvdev; ++ rdev->ops.hold_rx_buffer = rpmsg_virtio_hold_rx_buffer; ++ rdev->ops.release_rx_buffer = rpmsg_virtio_release_rx_buffer; ++ rdev->ops.get_tx_payload_buffer = rpmsg_virtio_get_tx_payload_buffer; ++ rdev->ops.send_offchannel_nocopy = rpmsg_virtio_send_offchannel_nocopy; + rdev->ops.send_offchannel_raw = rpmsg_virtio_send_offchannel_raw; + role = rpmsg_virtio_get_role(rvdev); + +-- +2.17.1 + diff --git a/openamp/0008-ns-acknowledge-the-received-creation-message.patch b/openamp/0008-ns-acknowledge-the-received-creation-message.patch new file mode 100644 index 0000000000..1f527b77ef --- /dev/null +++ b/openamp/0008-ns-acknowledge-the-received-creation-message.patch @@ -0,0 +1,132 @@ +From c2d2e03d9a0ddf9e1782c33fd459973c9bc7275a Mon Sep 17 00:00:00 2001 +From: Xiang Xiao +Date: Mon, 7 Jan 2019 02:15:42 +0800 +Subject: [PATCH 08/10] ns: acknowledge the received creation message + +the two phase handsake make the client could initiate the transfer +immediately without the server side send any dummy message first. + +Signed-off-by: Xiang Xiao +--- + lib/include/openamp/rpmsg.h | 1 + + lib/include/openamp/rpmsg_virtio.h | 1 + + lib/rpmsg/rpmsg.c | 7 +++++-- + lib/rpmsg/rpmsg_internal.h | 4 ++-- + lib/rpmsg/rpmsg_virtio.c | 12 +++++++++--- + 5 files changed, 18 insertions(+), 7 deletions(-) + +diff --git a/lib/include/openamp/rpmsg.h open-amp/lib/include/openamp/rpmsg.h +index 0b46ee1..318acd1 100644 +--- a/lib/include/openamp/rpmsg.h ++++ open-amp/lib/include/openamp/rpmsg.h +@@ -127,6 +127,7 @@ struct rpmsg_device { + rpmsg_ns_bind_cb ns_bind_cb; + struct rpmsg_device_ops ops; + bool support_ns; ++ bool support_ack; + }; + + /** +diff --git a/lib/include/openamp/rpmsg_virtio.h open-amp/lib/include/openamp/rpmsg_virtio.h +index 528b9bf..a2dd504 100644 +--- a/lib/include/openamp/rpmsg_virtio.h ++++ open-amp/lib/include/openamp/rpmsg_virtio.h +@@ -28,6 +28,7 @@ extern "C" { + + /* The feature bitmap for virtio rpmsg */ + #define VIRTIO_RPMSG_F_NS 0 /* RP supports name service notifications */ ++#define VIRTIO_RPMSG_F_ACK 1 /* RP supports name service acknowledge */ + + /** + * struct rpmsg_virtio_shm_pool - shared memory pool used for rpmsg buffers +diff --git a/lib/rpmsg/rpmsg.c open-amp/lib/rpmsg/rpmsg.c +index 0a8de1b..0cc80da 100644 +--- a/lib/rpmsg/rpmsg.c ++++ open-amp/lib/rpmsg/rpmsg.c +@@ -297,10 +297,13 @@ int rpmsg_create_ept(struct rpmsg_endpoint *ept, struct rpmsg_device *rdev, + + rpmsg_init_ept(ept, rdev, name, addr, dest, cb, unbind_cb); + +- if (rdev->support_ns && ept->dest_addr == RPMSG_ADDR_ANY) { ++ if (ept->name[0]) { + /* Send NS announcement to remote processor */ + metal_mutex_release(&rdev->lock); +- status = rpmsg_send_ns_message(ept, RPMSG_NS_CREATE); ++ if (rdev->support_ns && ept->dest_addr == RPMSG_ADDR_ANY) ++ status = rpmsg_send_ns_message(ept, RPMSG_NS_CREATE); ++ else if (rdev->support_ack && ept->dest_addr != RPMSG_ADDR_ANY) ++ status = rpmsg_send_ns_message(ept, RPMSG_NS_CREATE_ACK); + metal_mutex_acquire(&rdev->lock); + if (status) + rpmsg_unregister_endpoint(ept); +diff --git a/lib/rpmsg/rpmsg_internal.h open-amp/lib/rpmsg/rpmsg_internal.h +index 3db6b24..d513a56 100644 +--- a/lib/rpmsg/rpmsg_internal.h ++++ open-amp/lib/rpmsg/rpmsg_internal.h +@@ -44,12 +44,12 @@ extern "C" { + * + * @RPMSG_NS_CREATE: a new remote service was just created + * @RPMSG_NS_DESTROY: a known remote service was just destroyed +- * @RPMSG_NS_CREATE_WITH_ACK: a new remote service was just created waiting +- * acknowledgment. ++ * @RPMSG_NS_CREATE_ACK: acknowledge the previous creation message + */ + enum rpmsg_ns_flags { + RPMSG_NS_CREATE = 0, + RPMSG_NS_DESTROY = 1, ++ RPMSG_NS_CREATE_ACK = 2, + }; + + /** +diff --git a/lib/rpmsg/rpmsg_virtio.c open-amp/lib/rpmsg/rpmsg_virtio.c +index a525066..e57b1c2 100644 +--- a/lib/rpmsg/rpmsg_virtio.c ++++ open-amp/lib/rpmsg/rpmsg_virtio.c +@@ -586,13 +586,13 @@ static int rpmsg_virtio_ns_callback(struct rpmsg_endpoint *ept, void *data, + metal_mutex_acquire(&rdev->lock); + _ept = rpmsg_get_endpoint(rdev, name, RPMSG_ADDR_ANY, dest); + +- if (ns_msg->flags & RPMSG_NS_DESTROY) { ++ if (ns_msg->flags == RPMSG_NS_DESTROY) { + if (_ept) + _ept->dest_addr = RPMSG_ADDR_ANY; + metal_mutex_release(&rdev->lock); + if (_ept && _ept->ns_unbind_cb) + _ept->ns_unbind_cb(ept); +- } else { ++ } else if (ns_msg->flags == RPMSG_NS_CREATE) { + if (!_ept) { + /* + * send callback to application, that can +@@ -607,6 +607,11 @@ static int rpmsg_virtio_ns_callback(struct rpmsg_endpoint *ept, void *data, + _ept->dest_addr = dest; + metal_mutex_release(&rdev->lock); + } ++ } else { /* RPMSG_NS_CREATE_ACK */ ++ /* save the received destination address */ ++ if (_ept) ++ _ept->dest_addr = dest; ++ metal_mutex_release(&rdev->lock); + } + + return RPMSG_SUCCESS; +@@ -659,6 +664,7 @@ int rpmsg_init_vdev(struct rpmsg_virtio_device *rvdev, + #endif /*!VIRTIO_MASTER_ONLY*/ + vdev->features = rpmsg_virtio_get_features(rvdev); + rdev->support_ns = !!(vdev->features & (1 << VIRTIO_RPMSG_F_NS)); ++ rdev->support_ack = !!(vdev->features & (1 << VIRTIO_RPMSG_F_ACK)); + + #ifndef VIRTIO_SLAVE_ONLY + if (role == RPMSG_MASTER) { +@@ -754,7 +760,7 @@ int rpmsg_init_vdev(struct rpmsg_virtio_device *rvdev, + * Create name service announcement endpoint if device supports name + * service announcement feature. + */ +- if (rdev->support_ns) { ++ if (rdev->support_ns || rdev->support_ack) { + rpmsg_init_ept(&rdev->ns_ept, rdev, "NS", + RPMSG_NS_EPT_ADDR, RPMSG_NS_EPT_ADDR, + rpmsg_virtio_ns_callback, NULL); +-- +2.17.1 + diff --git a/openamp/0009-implement-rproc_virtio_read_config-rproc_virtio_writ.patch b/openamp/0009-implement-rproc_virtio_read_config-rproc_virtio_writ.patch new file mode 100644 index 0000000000..7faf2b302c --- /dev/null +++ b/openamp/0009-implement-rproc_virtio_read_config-rproc_virtio_writ.patch @@ -0,0 +1,119 @@ +From 1d94cd9ae8345543fa93c12cdc11ccbc2ca5b127 Mon Sep 17 00:00:00 2001 +From: Xiang Xiao +Date: Thu, 3 Jan 2019 14:20:48 +0800 +Subject: [PATCH 09/10] implement + rproc_virtio_read_config/rproc_virtio_write_config + +so the rpmsg could access the configuration space as needed + +Signed-off-by: Xiang Xiao +--- + lib/include/openamp/rpmsg_virtio.h | 14 +++++++++++ + lib/include/openamp/virtio.h | 1 + + lib/remoteproc/remoteproc_virtio.c | 40 ++++++++++++++++++++++++------ + 3 files changed, 47 insertions(+), 8 deletions(-) + +diff --git a/lib/include/openamp/rpmsg_virtio.h open-amp/lib/include/openamp/rpmsg_virtio.h +index a2dd504..e7c670e 100644 +--- a/lib/include/openamp/rpmsg_virtio.h ++++ open-amp/lib/include/openamp/rpmsg_virtio.h +@@ -86,6 +86,20 @@ rpmsg_virtio_get_features(struct rpmsg_virtio_device *rvdev) + return rvdev->vdev->func->get_features(rvdev->vdev); + } + ++static inline void ++rpmsg_virtio_read_config(struct rpmsg_virtio_device *rvdev, ++ uint32_t offset, void *dst, int length) ++{ ++ rvdev->vdev->func->read_config(rvdev->vdev, offset, dst, length); ++} ++ ++static inline void ++rpmsg_virtio_write_config(struct rpmsg_virtio_device *rvdev, ++ uint32_t offset, void *dst, int length) ++{ ++ rvdev->vdev->func->write_config(rvdev->vdev, offset, dst, length); ++} ++ + static inline int + rpmsg_virtio_create_virtqueues(struct rpmsg_virtio_device *rvdev, + int flags, unsigned int nvqs, +diff --git a/lib/include/openamp/virtio.h open-amp/lib/include/openamp/virtio.h +index 7085554..a93e0d9 100644 +--- a/lib/include/openamp/virtio.h ++++ open-amp/lib/include/openamp/virtio.h +@@ -100,6 +100,7 @@ struct virtio_device { + virtio_dev_reset_cb reset_cb; /**< user registered device callback */ + const struct virtio_dispatch *func; /**< Virtio dispatch table */ + void *priv; /**< TODO: remove pointer to virtio_device private data */ ++ unsigned int config_len; /**< config space length */ + unsigned int vrings_num; /**< number of vrings */ + struct virtio_vring_info *vrings_info; + }; +diff --git a/lib/remoteproc/remoteproc_virtio.c open-amp/lib/remoteproc/remoteproc_virtio.c +index e495d81..6a3b28b 100644 +--- a/lib/remoteproc/remoteproc_virtio.c ++++ open-amp/lib/remoteproc/remoteproc_virtio.c +@@ -126,20 +126,43 @@ static uint32_t rproc_virtio_negotiate_features(struct virtio_device *vdev, + static void rproc_virtio_read_config(struct virtio_device *vdev, + uint32_t offset, void *dst, int length) + { +- (void)vdev; +- (void)offset; +- (void)dst; +- (void)length; ++ struct remoteproc_virtio *rpvdev; ++ struct fw_rsc_vdev *vdev_rsc; ++ struct metal_io_region *io; ++ char *config; ++ ++ if (offset + length > vdev->config_len || offset + length < length) ++ return; ++ ++ rpvdev = metal_container_of(vdev, struct remoteproc_virtio, vdev); ++ vdev_rsc = rpvdev->vdev_rsc; ++ config = (char *)(&vdev_rsc->vring[vdev->vrings_num]); ++ io = rpvdev->vdev_rsc_io; ++ metal_io_block_read(io, ++ metal_io_virt_to_offset(io, config + offset), ++ dst, length); + } + + #ifndef VIRTIO_SLAVE_ONLY + static void rproc_virtio_write_config(struct virtio_device *vdev, + uint32_t offset, void *src, int length) + { +- (void)vdev; +- (void)offset; +- (void)src; +- (void)length; ++ struct remoteproc_virtio *rpvdev; ++ struct fw_rsc_vdev *vdev_rsc; ++ struct metal_io_region *io; ++ char *config; ++ ++ if (offset + length > vdev->config_len || offset + length < length) ++ return; ++ ++ rpvdev = metal_container_of(vdev, struct remoteproc_virtio, vdev); ++ vdev_rsc = rpvdev->vdev_rsc; ++ config = (char *)(&vdev_rsc->vring[vdev->vrings_num]); ++ io = rpvdev->vdev_rsc_io; ++ metal_io_block_write(io, ++ metal_io_virt_to_offset(io, config + offset), ++ src, length); ++ rpvdev->notify(rpvdev->priv, vdev->notifyid); + } + + static void rproc_virtio_reset_device(struct virtio_device *vdev) +@@ -220,6 +243,7 @@ rproc_virtio_create_vdev(unsigned int role, unsigned int notifyid, + vdev->notifyid = notifyid; + vdev->role = role; + vdev->reset_cb = rst_cb; ++ vdev->config_len = vdev_rsc->config_len; + vdev->vrings_num = num_vrings; + vdev->func = &remoteproc_virtio_dispatch_funcs; + +-- +2.17.1 + diff --git a/openamp/0010-Negotiate-individual-buffer-size-dynamically.patch b/openamp/0010-Negotiate-individual-buffer-size-dynamically.patch new file mode 100644 index 0000000000..60d1ce81c8 --- /dev/null +++ b/openamp/0010-Negotiate-individual-buffer-size-dynamically.patch @@ -0,0 +1,159 @@ +From f5f905a5c7b63e0b90a6b67e45d70305e6dfaa2c Mon Sep 17 00:00:00 2001 +From: anchao +Date: Mon, 10 Dec 2018 16:26:39 +0800 +Subject: [PATCH 10/10] Negotiate individual buffer size dynamically + +If slave support VIRTIO_RPMSG_F_BUFSZ(0x04) feature, master +determine the buffer size from config space(first 8 bytes), +otherwise the default size(512 bytes) will be used. + +Signed-off-by: anchao +--- + lib/include/openamp/remoteproc.h | 17 +++++++++++++++++ + lib/include/openamp/rpmsg_virtio.h | 4 ++++ + lib/rpmsg/rpmsg_virtio.c | 22 ++++++++++++++++------ + 3 files changed, 37 insertions(+), 6 deletions(-) + +diff --git a/lib/include/openamp/remoteproc.h open-amp/lib/include/openamp/remoteproc.h +index b34cb1a..ee9162a 100644 +--- a/lib/include/openamp/remoteproc.h ++++ open-amp/lib/include/openamp/remoteproc.h +@@ -303,6 +303,23 @@ struct fw_rsc_vdev { + struct fw_rsc_vdev_vring vring[0]; + } METAL_PACKED_END; + ++/** ++ * struct fw_rsc_config - configuration space declaration ++ * @txbuf_size: the tx buffer size ++ * @rxbuf_size: the rx buffer size ++ * @reserved: reserved (must be zero) ++ * ++ * This structure immediately follow fw_rsc_vdev to provide the config info. ++ */ ++METAL_PACKED_BEGIN ++struct fw_rsc_config { ++ /* The tx/rx individual buffer size(if VIRTIO_RPMSG_F_BUFSZ) */ ++ uint32_t txbuf_size; ++ uint32_t rxbuf_size; ++ uint32_t reserved[14]; /* Reserve for the future use */ ++ /* Put the customize config here */ ++} METAL_PACKED_END; ++ + /** + * struct fw_rsc_vendor - remote processor vendor specific resource + * @len: length of the resource +diff --git a/lib/include/openamp/rpmsg_virtio.h open-amp/lib/include/openamp/rpmsg_virtio.h +index e7c670e..e58c84e 100644 +--- a/lib/include/openamp/rpmsg_virtio.h ++++ open-amp/lib/include/openamp/rpmsg_virtio.h +@@ -16,6 +16,7 @@ + #include + #include + #include ++#include + + #if defined __cplusplus + extern "C" { +@@ -29,6 +30,7 @@ extern "C" { + /* The feature bitmap for virtio rpmsg */ + #define VIRTIO_RPMSG_F_NS 0 /* RP supports name service notifications */ + #define VIRTIO_RPMSG_F_ACK 1 /* RP supports name service acknowledge */ ++#define VIRTIO_RPMSG_F_BUFSZ 2 /* RP supports get buffer size from config space */ + + /** + * struct rpmsg_virtio_shm_pool - shared memory pool used for rpmsg buffers +@@ -45,6 +47,7 @@ struct rpmsg_virtio_shm_pool { + /** + * struct rpmsg_virtio_device - representation of a rpmsg device based on virtio + * @rdev: rpmsg device, first property in the struct ++ * @config: rpmsg config information + * @vdev: pointer to the virtio device + * @rvq: pointer to receive virtqueue + * @svq: pointer to send virtqueue +@@ -53,6 +56,7 @@ struct rpmsg_virtio_shm_pool { + */ + struct rpmsg_virtio_device { + struct rpmsg_device rdev; ++ struct fw_rsc_config config; + struct virtio_device *vdev; + struct virtqueue *rvq; + struct virtqueue *svq; +diff --git a/lib/rpmsg/rpmsg_virtio.c open-amp/lib/rpmsg/rpmsg_virtio.c +index e57b1c2..792a3b1 100644 +--- a/lib/rpmsg/rpmsg_virtio.c ++++ open-amp/lib/rpmsg/rpmsg_virtio.c +@@ -138,8 +138,8 @@ static void *rpmsg_virtio_get_tx_buffer(struct rpmsg_virtio_device *rvdev, + data = virtqueue_get_buffer(rvdev->svq, len, idx); + if (data == NULL) { + data = rpmsg_virtio_shm_pool_get_buffer(rvdev->shpool, +- RPMSG_BUFFER_SIZE); +- *len = RPMSG_BUFFER_SIZE; ++ rvdev->config.rxbuf_size); ++ *len = rvdev->config.rxbuf_size; + *idx = 0; + } + } +@@ -232,7 +232,7 @@ static int _rpmsg_virtio_get_buffer_size(struct rpmsg_virtio_device *rvdev) + * If device role is Master then buffers are provided by us, + * so just provide the macro. + */ +- length = RPMSG_BUFFER_SIZE - sizeof(struct rpmsg_hdr); ++ length = rvdev->config.rxbuf_size - sizeof(struct rpmsg_hdr); + } + #endif /*!VIRTIO_SLAVE_ONLY*/ + +@@ -649,11 +649,14 @@ int rpmsg_init_vdev(struct rpmsg_virtio_device *rvdev, + rvdev->vdev = vdev; + rdev->ns_bind_cb = ns_bind_cb; + vdev->priv = rvdev; ++ rvdev->config.txbuf_size = RPMSG_BUFFER_SIZE; ++ rvdev->config.rxbuf_size = RPMSG_BUFFER_SIZE; + rdev->ops.hold_rx_buffer = rpmsg_virtio_hold_rx_buffer; + rdev->ops.release_rx_buffer = rpmsg_virtio_release_rx_buffer; + rdev->ops.get_tx_payload_buffer = rpmsg_virtio_get_tx_payload_buffer; + rdev->ops.send_offchannel_nocopy = rpmsg_virtio_send_offchannel_nocopy; + rdev->ops.send_offchannel_raw = rpmsg_virtio_send_offchannel_raw; ++ + role = rpmsg_virtio_get_role(rvdev); + + #ifndef VIRTIO_MASTER_ONLY +@@ -666,6 +669,13 @@ int rpmsg_init_vdev(struct rpmsg_virtio_device *rvdev, + rdev->support_ns = !!(vdev->features & (1 << VIRTIO_RPMSG_F_NS)); + rdev->support_ack = !!(vdev->features & (1 << VIRTIO_RPMSG_F_ACK)); + ++ if (vdev->features & (1 << VIRTIO_RPMSG_F_BUFSZ)) { ++ rpmsg_virtio_read_config(rvdev, ++ 0, ++ &rvdev->config, ++ sizeof(rvdev->config)); ++ } ++ + #ifndef VIRTIO_SLAVE_ONLY + if (role == RPMSG_MASTER) { + /* +@@ -726,11 +736,11 @@ int rpmsg_init_vdev(struct rpmsg_virtio_device *rvdev, + unsigned int idx; + void *buffer; + +- vqbuf.len = RPMSG_BUFFER_SIZE; ++ vqbuf.len = rvdev->config.txbuf_size; + for (idx = 0; idx < rvdev->rvq->vq_nentries; idx++) { + /* Initialize TX virtqueue buffers for remote device */ + buffer = rpmsg_virtio_shm_pool_get_buffer(shpool, +- RPMSG_BUFFER_SIZE); ++ rvdev->config.txbuf_size); + + if (!buffer) { + return RPMSG_ERR_NO_BUFF; +@@ -741,7 +751,7 @@ int rpmsg_init_vdev(struct rpmsg_virtio_device *rvdev, + metal_io_block_set(shm_io, + metal_io_virt_to_offset(shm_io, + buffer), +- 0x00, RPMSG_BUFFER_SIZE); ++ 0x00, rvdev->config.txbuf_size); + status = + virtqueue_add_buffer(rvdev->rvq, &vqbuf, 0, 1, + buffer); +-- +2.17.1 + diff --git a/openamp/Makefile b/openamp/Makefile index b9e82ce3c2..9f2c254fdf 100644 --- a/openamp/Makefile +++ b/openamp/Makefile @@ -41,6 +41,8 @@ CSRCS = VPATH := $(SRCDIR) DEPPATH = --dep-path . +VERSION ?= 2020.01.0 + include libmetal.defs include open-amp.defs @@ -73,7 +75,6 @@ dirlinks:: depend: .depend clean: - $(foreach obj,$(OBJS),$(call DELFILE, $(obj))) $(call DELFILE, $(BIN)) $(call CLEAN) diff --git a/openamp/libmetal.defs b/openamp/libmetal.defs index cf5b46fcc7..d8510115c7 100644 --- a/openamp/libmetal.defs +++ b/openamp/libmetal.defs @@ -37,15 +37,10 @@ ifeq ($(CONFIG_OPENAMP),y) ifeq ($(CONFIG_ARCH), sim) LIBMETAL_ARCH = x86_64 -else -LIBMETAL_ARCH = $(subst -,,$(CONFIG_ARCH)) +else ifeq ($(CONFIG_ARCH), risc-v) +LIBMETAL_ARCH = riscv endif -LIBMETAL_HDRS += $(wildcard libmetal/lib/compiler/gcc/*.h) -LIBMETAL_HDRS += $(wildcard libmetal/lib/processor/$(LIBMETAL_ARCH)/*.h) -LIBMETAL_HDRS += $(wildcard libmetal/lib/system/nuttx/*.h) -LIBMETAL_HDRS += $(wildcard libmetal/lib/*.h) - CSRCS += libmetal/lib/system/nuttx/condition.c CSRCS += libmetal/lib/system/nuttx/device.c CSRCS += libmetal/lib/system/nuttx/init.c @@ -77,11 +72,21 @@ LIBMETAL_HDRS_SEDEXP := \ s/@PROJECT_MACHINE_UPPER@/$(CONFIG_ARCH_CHIP)/g; \ s/cmakedefine/undef/g" -.libmetal_headers: $(LIBMETAL_HDRS) - $(foreach headers,$(LIBMETAL_HDRS), \ - $(eval hobj := $(patsubst libmetal$(DELIM)lib$(DELIM)%,$(TOPDIR)$(DELIM)include$(DELIM)metal$(DELIM)%,$(headers))) \ +libmetal.zip: + $(Q) wget https://github.com/OpenAMP/libmetal/archive/v$(VERSION).zip -O libmetal.zip + $(Q) unzip -o libmetal.zip + $(Q) mv libmetal-$(VERSION) libmetal + $(Q) patch -p0 < 0001-nuttx-change-sched_kfree-to-metal_free_memory.patch + +.libmetal_headers: libmetal.zip + $(eval headers := $(wildcard libmetal/lib/compiler/gcc/*.h)) + $(eval headers += $(wildcard libmetal/lib/processor/$(LIBMETAL_ARCH)/*.h)) + $(eval headers += $(wildcard libmetal/lib/system/nuttx/*.h)) + $(eval headers += $(wildcard libmetal/lib/*.h)) + $(foreach header,$(headers), \ + $(eval hobj := $(patsubst libmetal$(DELIM)lib$(DELIM)%,$(TOPDIR)$(DELIM)include$(DELIM)metal$(DELIM)%,$(header))) \ $(shell if [ ! -d $(dir $(hobj)) ];then mkdir -p $(dir $(hobj)); fi) \ - $(shell sed $(LIBMETAL_HDRS_SEDEXP) $(headers) > $(hobj)) \ + $(shell sed $(LIBMETAL_HDRS_SEDEXP) $(header) > $(hobj)) \ ) touch $@ @@ -89,6 +94,8 @@ dirlinks:: .libmetal_headers distclean:: $(call DELDIR, $(TOPDIR)$(DELIM)include$(DELIM)metal) + $(call DELDIR, libmetal) + $(call DELFILE, libmetal.zip) $(call DELFILE, .libmetal_headers) endif diff --git a/openamp/open-amp.defs b/openamp/open-amp.defs index 6391eec58d..dda86d905b 100644 --- a/openamp/open-amp.defs +++ b/openamp/open-amp.defs @@ -35,8 +35,6 @@ ifeq ($(CONFIG_OPENAMP),y) -OPENAMP_HDRS += $(wildcard open-amp/lib/include/openamp/*.h) - CSRCS += open-amp/lib/remoteproc/elf_loader.c CSRCS += open-amp/lib/remoteproc/remoteproc.c CSRCS += open-amp/lib/remoteproc/remoteproc_virtio.c @@ -46,15 +44,33 @@ CSRCS += open-amp/lib/rpmsg/rpmsg_virtio.c CSRCS += open-amp/lib/virtio/virtio.c CSRCS += open-amp/lib/virtio/virtqueue.c -.openamp_headers: $(OPENAMP_HDRS) +open-amp.zip: + $(Q) wget https://github.com/OpenAMP/open-amp/archive/v$(VERSION).zip -O open-amp.zip + $(Q) unzip -o open-amp.zip + $(Q) mv open-amp-$(VERSION) open-amp + $(Q) patch -p0 < 0001-rpmsg-remove-the-address-check-in-rpmsg_send-rpmsg_t.patch + $(Q) patch -p0 < 0002-rpmsg-merge-rpmsg_register_endpoint-into-rpmsg_init_.patch + $(Q) patch -p0 < 0003-rpmsg-shouldn-t-allocate-0-1023-address-in-rpmsg_cre.patch + $(Q) patch -p0 < 0004-rpmsg-wait-ept-ready-in-rpmsg_send.patch + $(Q) patch -p0 < 0005-rpmsg-return-fail-if-either-source-or-destination-ad.patch + $(Q) patch -p0 < 0006-remoteproc_mmap-support-va-to-pa-da-conversion.patch + $(Q) patch -p0 < 0007-rpmsg-bring-back-zero-copy-transfer.patch + $(Q) patch -p0 < 0008-ns-acknowledge-the-received-creation-message.patch + $(Q) patch -p0 < 0009-implement-rproc_virtio_read_config-rproc_virtio_writ.patch + $(Q) patch -p0 < 0010-Negotiate-individual-buffer-size-dynamically.patch + +.openamp_headers: open-amp.zip + $(eval headers := $(wildcard open-amp/lib/include/openamp/*.h)) $(shell mkdir -p $(TOPDIR)$(DELIM)include$(DELIM)openamp$(DELIM)) - $(foreach header,$^,$(shell cp -rf $(header) $(TOPDIR)$(DELIM)include$(DELIM)openamp$(DELIM))) + $(foreach header,$(headers),$(shell cp -rf $(header) $(TOPDIR)$(DELIM)include$(DELIM)openamp$(DELIM))) touch $@ dirlinks:: .openamp_headers distclean:: $(call DELDIR, $(TOPDIR)$(DELIM)include$(DELIM)openamp$(DELIM)) + $(call DELDIR, open-amp) + $(call DELFILE, open-amp.zip) $(call DELFILE, .openamp_headers) endif