From 906f2621761ab0a022f86b76bd27a7fabc15bb10 Mon Sep 17 00:00:00 2001 From: Wendy Liang Date: Thu, 14 Mar 2019 10:50:25 -0700 Subject: [PATCH 1/4] examples: linux: zynqmp: Introduce common IPI APIs Introduce common APIs for Inter-Processor Interrupt / Interface initialization and notification. Signed-off-by: Wendy Liang --- .../linux/zynqmp/zynqmp_amp_demo/common.h | 39 ++++++++++++++++++- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/examples/system/linux/zynqmp/zynqmp_amp_demo/common.h b/examples/system/linux/zynqmp/zynqmp_amp_demo/common.h index e7a669f2..4264eb4d 100644 --- a/examples/system/linux/zynqmp/zynqmp_amp_demo/common.h +++ b/examples/system/linux/zynqmp/zynqmp_amp_demo/common.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2017, Xilinx Inc. and Contributors. All rights reserved. - * Copyright (C) 2022, Advanced Micro Devices, Inc. + * Copyright (c) 2017-2022, Xilinx Inc. and Contributors. All rights reserved. + * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -196,4 +196,39 @@ static inline void print_demo(char *name) LPRINTF("****** libmetal demo: %s ******\n", name); } +/** + * @brief ipi_kick_register_handler() - register for IPI kick handler + * + * @param[in] hd - handler function + * @param[in] priv - private data will be passed to the handler + */ +void ipi_kick_register_handler(metal_irq_handler hd, void *priv); + +/** + * @brief init_ipi() - Initialize IPI + * + * @return return 0 for success, negative value for failure. + */ +int init_ipi(void); + +/** + * @brief deinit_ipi() - Deinitialize IPI + */ +void deinit_ipi(void); + +/** + * @brief kick_ipi() - kick remote with IPI + */ +void kick_ipi(void *msg); + +/** + * @brief disable_ipi_kick() - disable IPI interrupt from remote kick + */ +void disable_ipi_kick(void); + +/** + * @brief enable_ipi_kick() - enable IPI interrupt from remote kick + */ +void enable_ipi_kick(void); + #endif /* __COMMON_H__ */ From e2c206f645d4f102067f7b5df129d98dbcbba4d0 Mon Sep 17 00:00:00 2001 From: Wendy Liang Date: Thu, 14 Mar 2019 10:52:39 -0700 Subject: [PATCH 2/4] examples: linux: zynqmp: Add IPI uio based API implementation Add IPI uio based API implementation. Signed-off-by: Wendy Liang --- .../linux/zynqmp/zynqmp_amp_demo/ipi-uio.c | 145 ++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 examples/system/linux/zynqmp/zynqmp_amp_demo/ipi-uio.c diff --git a/examples/system/linux/zynqmp/zynqmp_amp_demo/ipi-uio.c b/examples/system/linux/zynqmp/zynqmp_amp_demo/ipi-uio.c new file mode 100644 index 00000000..9704f9a1 --- /dev/null +++ b/examples/system/linux/zynqmp/zynqmp_amp_demo/ipi-uio.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2017-2022, Xilinx Inc. and Contributors. All rights reserved. + * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "common.h" + +struct ipi_channel { + struct metal_device *ipi_dev; /**< ipi metal device */ + struct metal_io_region *ipi_io; /**< ipi metal I/O region */ + int ipi_irq; /**< ipi irq id */ + uint32_t ipi_mask; /**< remote IPI mask */ + metal_irq_handler ipi_kick_cb; /**< IPI kick callback */ + void *ipi_kick_priv; /**< IPI kick callback private data */ +}; + +static struct ipi_channel ipi_chnl; + +/** + * @brief ipi_irq_handler() - IPI interrupt handler + * It will clear the notified flag to mark it's got an IPI interrupt. + * It will stop the RPU->APU timer and will clear the notified + * flag to mark it's got an IPI interrupt + * + * @param[in] vect_id - IPI interrupt vector ID + * @param[in/out] priv - communication channel data for this application. + * + * @return - If the IPI interrupt is triggered by its remote, it returns + * METAL_IRQ_HANDLED. It returns METAL_IRQ_NOT_HANDLED, if it is + * not the interrupt it expected. + * + */ +static int _ipi_irq_handler (int vect_id, void *priv) +{ + uint32_t val; + struct ipi_channel *chnl = (struct ipi_channel *)priv; + struct metal_io_region *io; + + (void)vect_id; + + io = chnl->ipi_io; + val = metal_io_read32(io, IPI_ISR_OFFSET); + if (val & chnl->ipi_mask) { + if (chnl->ipi_kick_cb) + chnl->ipi_kick_cb(vect_id, chnl->ipi_kick_priv); + metal_io_write32(io, IPI_ISR_OFFSET, chnl->ipi_mask); + return METAL_IRQ_HANDLED; + } + return METAL_IRQ_NOT_HANDLED; +} + +static void _enable_ipi_intr(struct ipi_channel *chnl) +{ + metal_irq_enable(chnl->ipi_irq); + /* Enable IPI interrupt */ + metal_io_write32(chnl->ipi_io, IPI_IER_OFFSET, chnl->ipi_mask); +} + +static void _disable_ipi_intr(struct ipi_channel *chnl) +{ + /* disable IPI interrupt */ + metal_io_write32(chnl->ipi_io, IPI_IDR_OFFSET, chnl->ipi_mask); + metal_irq_disable(ipi_chnl.ipi_irq); +} + +void ipi_kick_register_handler(metal_irq_handler hd, void *priv) +{ + ipi_chnl.ipi_kick_cb = hd; + ipi_chnl.ipi_kick_priv = priv; +} + +int init_ipi(void) +{ + struct metal_device *dev; + struct metal_io_region *io; + int ret; + + /* Open IPI device */ + ret = metal_device_open(BUS_NAME, IPI_DEV_NAME, &dev); + if (ret) { + LPERROR("Failed to open device %s.\n", IPI_DEV_NAME); + return ret; + } + + /* Get IPI device IO region */ + io = metal_device_io_region(dev, 0); + if (!io) { + LPERROR("Failed to map io region for %s.\n", dev->name); + ret = -ENODEV; + metal_device_close(dev); + return ret; + } + ipi_chnl.ipi_dev = dev; + ipi_chnl.ipi_io = io; + + /* Get the IPI IRQ from the opened IPI device */ + ipi_chnl.ipi_irq = (intptr_t)dev->irq_info; + + ipi_chnl.ipi_mask = IPI_MASK; + /* disable IPI interrupt */ + _disable_ipi_intr(&ipi_chnl); + /* clear old IPI interrupt */ + metal_io_write32(io, IPI_ISR_OFFSET, IPI_MASK); + /* Register IPI irq handler */ + metal_irq_register(ipi_chnl.ipi_irq, _ipi_irq_handler, &ipi_chnl); + return 0; +} + +void deinit_ipi(void) +{ + /* disable IPI interrupt */ + _disable_ipi_intr(&ipi_chnl); + /* unregister IPI irq handler by setting the handler to 0 */ + metal_irq_unregister(ipi_chnl.ipi_irq); + if (ipi_chnl.ipi_dev) { + metal_device_close(ipi_chnl.ipi_dev); + ipi_chnl.ipi_dev = NULL; + } +} + +void kick_ipi(void *msg) +{ + (void)msg; + metal_io_write32(ipi_chnl.ipi_io, IPI_TRIG_OFFSET, ipi_chnl.ipi_mask); +} + +void disable_ipi_kick(void) +{ + _disable_ipi_intr(&ipi_chnl); +} + +void enable_ipi_kick(void) +{ + _enable_ipi_intr(&ipi_chnl); +} From 975012001e4ce1e9c3490918b823a946c7786ad3 Mon Sep 17 00:00:00 2001 From: Wendy Liang Date: Mon, 18 Mar 2019 08:49:21 -0700 Subject: [PATCH 3/4] examples: linux: add IPI with R5 rproc kick sysfs impelmentation Add IPI mailbox IPI implementation with the remoteproc kick sysfs API. Signed-off-by: Wendy Liang --- .../linux/zynqmp/zynqmp_amp_demo/ipi-mb.c | 231 ++++++++++++++++++ 1 file changed, 231 insertions(+) create mode 100644 examples/system/linux/zynqmp/zynqmp_amp_demo/ipi-mb.c diff --git a/examples/system/linux/zynqmp/zynqmp_amp_demo/ipi-mb.c b/examples/system/linux/zynqmp/zynqmp_amp_demo/ipi-mb.c new file mode 100644 index 00000000..be27d6b7 --- /dev/null +++ b/examples/system/linux/zynqmp/zynqmp_amp_demo/ipi-mb.c @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2017-2022, Xilinx Inc. and Contributors. All rights reserved. + * Copyright (c) 2022-2023 Advanced Micro Devices, Inc. All Rights Reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "common.h" + +#define RPROC_SYSFS "/sys/class/remoteproc/remoteproc0" +#define RPROC_SYSFS_KICK RPROC_SYSFS "/kick" +#define RPROC_SYSFS_REMOTE_KICK RPROC_SYSFS "/remote_kick" + +struct ipi_channel { + char *kickf; /**< IPI kick sysfs path */ + char *rkickf; /**< IPI remote kick sysfs path */ + int rkick_fd; /**< IPI remote kick file descriptor */ + atomic_int ipi_enabled; /**< flag to indicate if IPI is enabled */ + atomic_int ipi_handling_wakeup; /**< IPI handling wakeup */ + metal_irq_handler ipi_kick_cb; /**< IPI kick callback */ + void *ipi_kick_priv; /**< IPI kick callback private data */ +}; + +static struct ipi_channel ipi_chnl; +static pthread_t ipi_pthread; +static int ipi_handling_stop_fd; + +/** + * @brief ipi_kick_handling() - IPI kick handling + * + * It will listening to the remote kick sysfs file. + * It will call the registered handler if there is a kick from the + * remote. + * + * @param[in] args - argument of pthread. + * @return NULL. + * + */ +static void *_ipi_kick_handling(void *args) +{ + int rkick_fd; + sigset_t set; + + (void)args; + /* unblock all signals */ + sigfillset(&set); + pthread_sigmask(SIG_UNBLOCK, &set, NULL); + rkick_fd = ipi_chnl.rkick_fd; + while (1) { + char val[2] = {0, 0}; + int ret; + + lseek(rkick_fd, 0, SEEK_SET); + ret = read(rkick_fd, &val, sizeof(val)); + if (ret < 0) { + LPERROR("failed to read %s.\n", ipi_chnl.rkickf); + return NULL; + } + if (val[0] == '1') { + if (atomic_load(&ipi_chnl.ipi_enabled) == 0) { + int v; + + v = atomic_load(&ipi_chnl.ipi_handling_wakeup); + syscall(SYS_futex, + &ipi_chnl.ipi_handling_wakeup, + FUTEX_WAIT, v, NULL, NULL, 0); + } + if (ipi_chnl.ipi_kick_cb) { + ipi_chnl.ipi_kick_cb(rkick_fd, + ipi_chnl.ipi_kick_priv); + } + lseek(rkick_fd, 0, SEEK_SET); + ret = write(rkick_fd, &val, sizeof(val)); + if (ret < 0) { + LPERROR("failed to write %s.\n", + ipi_chnl.rkickf); + return NULL; + } + } else { + struct pollfd fds[2]; + + fds[0].fd = rkick_fd; + fds[0].events = POLLPRI; + fds[1].fd = ipi_handling_stop_fd; + fds[1].events = POLLIN; + ret = poll(fds, 2, -1); + if (ret == 0) { + LPERROR("polling %s times out.\n", + ipi_chnl.rkickf); + return NULL; + } else if (fds[1].revents & POLLIN) { + return NULL; + + } else if (ret < 0) { + LPERROR("polling %s failed, %s.\n", + ipi_chnl.rkickf, strerror(ret)); + return NULL; + } + } + } +} + +static void _enable_ipi_intr(struct ipi_channel *chnl) +{ + int exp = 0; + + atomic_compare_exchange_strong(&chnl->ipi_enabled, &exp, 1); + if (exp == 0) { + atomic_fetch_add(&chnl->ipi_handling_wakeup, 1); + syscall(SYS_futex, &chnl->ipi_handling_wakeup, FUTEX_WAKE, + 1, NULL, NULL, 0); + } +} + +static void _disable_ipi_intr(struct ipi_channel *chnl) +{ + atomic_store(&chnl->ipi_enabled, 0); +} + +void ipi_kick_register_handler(metal_irq_handler hd, void *priv) +{ + ipi_chnl.ipi_kick_cb = hd; + ipi_chnl.ipi_kick_priv = priv; +} + +int init_ipi(void) +{ + int ret; + int val = 0; + + atomic_init(&ipi_chnl.ipi_enabled, 0); + atomic_init(&ipi_chnl.ipi_handling_wakeup, 0); + ipi_chnl.kickf = RPROC_SYSFS_KICK; + ipi_chnl.rkickf = RPROC_SYSFS_REMOTE_KICK; + + ret = open(ipi_chnl.rkickf, O_RDWR); + if (ret < 0) { + LPERROR("failed to open %s, %s.\n", + ipi_chnl.rkickf, strerror(ret)); + return ret; + } + ipi_chnl.rkick_fd = ret; + /** Write to the remote kick fd to clear pending IPI interrupt */ + ret = write(ipi_chnl.rkick_fd, &val, sizeof(val)); + if (ret < 0) { + LPERROR("failed to write to %s, %s.\n", + ipi_chnl.rkickf, strerror(ret)); + close(ipi_chnl.rkick_fd); + return ret; + } + + ipi_handling_stop_fd = eventfd(0, 0); + if (ipi_handling_stop_fd < 0) { + LPERROR("failed to create ipi handling stop fd.\n"); + close(ipi_chnl.rkick_fd); + return ipi_handling_stop_fd; + } + + ret = pthread_create(&ipi_pthread, NULL, _ipi_kick_handling, NULL); + if (ret < 0) { + LPERROR("failed to create IPI handling thread.\n"); + close(ipi_chnl.rkick_fd); + close(ipi_handling_stop_fd); + return ret; + } + return 0; +} + +void deinit_ipi(void) +{ + int ret; + uint64_t val = 1; + + ret = write(ipi_handling_stop_fd, &val, sizeof(val)); + if (ret < 0) { + LPERROR("failed to notify deinit ipi, %s.\n", strerror(ret)); + } + atomic_fetch_add(&ipi_chnl.ipi_handling_wakeup, 1); + syscall(SYS_futex, &ipi_chnl.ipi_handling_wakeup, FUTEX_WAKE, + 1, NULL, NULL, 0); + ret = pthread_join(ipi_pthread, NULL); + if (ret) { + LPERROR("failed to join IPI thread: %d.\n", ret); + } + close(ipi_handling_stop_fd); + close(ipi_chnl.rkick_fd); +} + +void kick_ipi(void *msg) +{ + int fd, ret; + int buf = -1; + + (void)msg; + fd = open(ipi_chnl.kickf, O_WRONLY); + if (fd < 0) { + LPERROR("failed to open %s.\n", ipi_chnl.kickf); + return; + } + + ret = write(fd, &buf, sizeof(buf)); + if (ret <= 0) + LPERROR("failed to write to %s, %s.\n", + ipi_chnl.kickf, strerror(ret)); + close(fd); +} + +void disable_ipi_kick(void) +{ + _disable_ipi_intr(&ipi_chnl); +} + +void enable_ipi_kick(void) +{ + _enable_ipi_intr(&ipi_chnl); +} From 949d08ed37eac9929b619257b1ea723bbce04215 Mon Sep 17 00:00:00 2001 From: Wendy Liang Date: Mon, 18 Mar 2019 08:56:01 -0700 Subject: [PATCH 4/4] examples: linux: zynqmp: Use IPI commit API Change to use IPI common API so that it can swtich from IPI uio implementaion or IPI rproc sysfs implementation. Signed-off-by: Wendy Liang --- .../zynqmp/zynqmp_amp_demo/CMakeLists.txt | 35 +++++++++ .../zynqmp/zynqmp_amp_demo/ipi_latency_demo.c | 67 ++++------------- .../zynqmp/zynqmp_amp_demo/ipi_shmem_demo.c | 75 +++++-------------- .../zynqmp_amp_demo/shmem_atomic_demo.c | 72 +++++------------- .../zynqmp_amp_demo/shmem_latency_demo.c | 64 ++++------------ .../zynqmp_amp_demo/shmem_throughput_demo.c | 68 ++++------------- 6 files changed, 114 insertions(+), 267 deletions(-) diff --git a/examples/system/linux/zynqmp/zynqmp_amp_demo/CMakeLists.txt b/examples/system/linux/zynqmp/zynqmp_amp_demo/CMakeLists.txt index 1bdb59b8..11c178fc 100644 --- a/examples/system/linux/zynqmp/zynqmp_amp_demo/CMakeLists.txt +++ b/examples/system/linux/zynqmp/zynqmp_amp_demo/CMakeLists.txt @@ -11,6 +11,41 @@ get_property (_ec_flgs GLOBAL PROPERTY "PROJECT_EC_FLAGS") foreach (_app libmetal_amp_demo libmetal_amp_demod) set (_src ${CMAKE_CURRENT_SOURCE_DIR}/${_app}.c) list(APPEND _src ${_src_common}) + list(APPEND _src ${CMAKE_CURRENT_SOURCE_DIR}/ipi-uio.c) + list(APPEND _src ${CMAKE_CURRENT_SOURCE_DIR}/shmem_demo.c) + list(APPEND _src ${CMAKE_CURRENT_SOURCE_DIR}/shmem_atomic_demo.c) + list(APPEND _src ${CMAKE_CURRENT_SOURCE_DIR}/ipi_shmem_demo.c) + list(APPEND _src ${CMAKE_CURRENT_SOURCE_DIR}/ipi_latency_demo.c) + list(APPEND _src ${CMAKE_CURRENT_SOURCE_DIR}/shmem_latency_demo.c) + list(APPEND _src ${CMAKE_CURRENT_SOURCE_DIR}/shmem_throughput_demo.c) + if (WITH_SHARED_LIB) + add_executable (${_app}-share ${_src}) + if (PROJECT_EC_FLAGS) + string(REPLACE " " ";" _ec_flgs ${PROJECT_EC_FLAGS}) + target_compile_options (${_app}-share PUBLIC ${_ec_flgs}) + endif (PROJECT_EC_FLAGS) + target_link_libraries (${_app}-share ${PROJECT_NAME}-shared ${_deps}) + install (TARGETS ${_app}-share RUNTIME DESTINATION bin) + add_dependencies (${_app}-share ${PROJECT_NAME}-shared) + endif (WITH_SHARED_LIB) + + if (WITH_STATIC_LIB) + if (${PROJECT_SYSTEM} STREQUAL "linux") + add_executable (${_app}-static ${_src}) + if (PROJECT_EC_FLAGS) + string(REPLACE " " ";" _ec_flgs ${PROJECT_EC_FLAGS}) + target_compile_options (${_app}-static PUBLIC ${_ec_flgs}) + endif (PROJECT_EC_FLAGS) + target_link_libraries (${_app}-static ${PROJECT_NAME}-static ${_deps}) + install (TARGETS ${_app}-static RUNTIME DESTINATION bin) + endif (${PROJECT_SYSTEM} STREQUAL "linux") + endif (WITH_STATIC_LIB) +endforeach (_app) + +foreach (_app libmetal_amp_mb_shmem) + set (_src ${CMAKE_CURRENT_SOURCE_DIR}/libmetal_amp_demo.c) + list(APPEND _src ${_src_common}) + list(APPEND _src ${CMAKE_CURRENT_SOURCE_DIR}/ipi-mb.c) list(APPEND _src ${CMAKE_CURRENT_SOURCE_DIR}/shmem_demo.c) list(APPEND _src ${CMAKE_CURRENT_SOURCE_DIR}/shmem_atomic_demo.c) list(APPEND _src ${CMAKE_CURRENT_SOURCE_DIR}/ipi_shmem_demo.c) diff --git a/examples/system/linux/zynqmp/zynqmp_amp_demo/ipi_latency_demo.c b/examples/system/linux/zynqmp/zynqmp_amp_demo/ipi_latency_demo.c index 2bebf366..53efaaba 100644 --- a/examples/system/linux/zynqmp/zynqmp_amp_demo/ipi_latency_demo.c +++ b/examples/system/linux/zynqmp/zynqmp_amp_demo/ipi_latency_demo.c @@ -51,13 +51,10 @@ #define ITERATIONS 1000 struct channel_s { - struct metal_device *ipi_dev; /* IPI metal device */ - struct metal_io_region *ipi_io; /* IPI metal i/o region */ struct metal_device *shm_dev; /* Shared memory metal device */ struct metal_io_region *shm_io; /* Shared memory metal i/o region */ struct metal_device *ttc_dev; /* TTC metal device */ struct metal_io_region *ttc_io; /* TTC metal i/o region */ - uint32_t ipi_mask; /* RPU IPI mask */ atomic_flag remote_nkicked; /* 0 - kicked from remote */ }; @@ -129,20 +126,14 @@ static inline void stop_timer(struct metal_io_region *ttc_io, static int ipi_irq_handler (int vect_id, void *priv) { struct channel_s *ch = (struct channel_s *)priv; - uint32_t val; (void)vect_id; if (ch) { - val = metal_io_read32(ch->ipi_io, IPI_ISR_OFFSET); - if (val & ch->ipi_mask) { - /* stop RPU -> APU timer */ - stop_timer(ch->ttc_io, TTC_CNT_RPU_TO_APU); - metal_io_write32(ch->ipi_io, IPI_ISR_OFFSET, - ch->ipi_mask); - atomic_flag_clear(&ch->remote_nkicked); - return METAL_IRQ_HANDLED; - } + /* stop RPU -> APU timer */ + stop_timer(ch->ttc_io, TTC_CNT_RPU_TO_APU); + atomic_flag_clear(&ch->remote_nkicked); + return METAL_IRQ_HANDLED; } return METAL_IRQ_NOT_HANDLED; } @@ -175,7 +166,7 @@ static int measure_ipi_latency(struct channel_s *ch) /* Reset TTC counter */ reset_timer(ch->ttc_io, TTC_CNT_APU_TO_RPU); /* Kick IPI to notify the remote */ - metal_io_write32(ch->ipi_io, IPI_TRIG_OFFSET, ch->ipi_mask); + kick_ipi(NULL); /* irq handler stops timer for rpu->apu irq */ wait_for_notified(&ch->remote_nkicked); @@ -186,7 +177,7 @@ static int measure_ipi_latency(struct channel_s *ch) /* write to shared memory to indicate demo has finished */ metal_io_write32(ch->shm_io, SHM_DEMO_CNTRL_OFFSET, 0); /* Kick IPI to notify the remote */ - metal_io_write32(ch->ipi_io, IPI_TRIG_OFFSET, ch->ipi_mask); + kick_ipi(NULL); /* report avg latencies */ LPRINTF("IPI latency result with %i iterations:\n", ITERATIONS); @@ -203,7 +194,6 @@ int ipi_latency_demo() struct metal_device *dev; struct metal_io_region *io; struct channel_s ch; - int ipi_irq; int ret = 0; print_demo("IPI latency"); @@ -243,56 +233,29 @@ int ipi_latency_demo() ch.ttc_dev = dev; ch.ttc_io = io; - /* Open IPI device */ - ret = metal_device_open(BUS_NAME, IPI_DEV_NAME, &dev); - if (ret) { - LPERROR("Failed to open device %s.\n", IPI_DEV_NAME); - goto out; - } - - /* Get IPI device IO region */ - io = metal_device_io_region(dev, 0); - if (!io) { - LPERROR("Failed to map io region for %s.\n", dev->name); - ret = -ENODEV; - goto out; - } - ch.ipi_dev = dev; - ch.ipi_io = io; - - /* Get the IPI IRQ from the opened IPI device */ - ipi_irq = (intptr_t)ch.ipi_dev->irq_info; - - /* disable IPI interrupt */ - metal_io_write32(ch.ipi_io, IPI_IDR_OFFSET, IPI_MASK); - /* clear old IPI interrupt */ - metal_io_write32(ch.ipi_io, IPI_ISR_OFFSET, IPI_MASK); /* initialize remote_nkicked */ ch.remote_nkicked = (atomic_flag)ATOMIC_FLAG_INIT; atomic_flag_test_and_set(&ch.remote_nkicked); - ch.ipi_mask = IPI_MASK; - /* Register IPI irq handler */ - metal_irq_register(ipi_irq, ipi_irq_handler, &ch); - metal_irq_enable(ipi_irq); - /* Enable IPI interrupt */ - metal_io_write32(ch.ipi_io, IPI_IER_OFFSET, IPI_MASK); + + ret = init_ipi(); + if (ret) { + goto out; + } + ipi_kick_register_handler(ipi_irq_handler, &ch); + enable_ipi_kick(); /* Run atomic operation demo */ ret = measure_ipi_latency(&ch); /* disable IPI interrupt */ - metal_io_write32(ch.ipi_io, IPI_IDR_OFFSET, IPI_MASK); - /* unregister IPI irq handler by setting the handler to 0 */ - metal_irq_disable(ipi_irq); - metal_irq_unregister(ipi_irq); + disable_ipi_kick(); + deinit_ipi(); out: if (ch.ttc_dev) metal_device_close(ch.ttc_dev); if (ch.shm_dev) metal_device_close(ch.shm_dev); - if (ch.ipi_dev) - metal_device_close(ch.ipi_dev); return ret; } diff --git a/examples/system/linux/zynqmp/zynqmp_amp_demo/ipi_shmem_demo.c b/examples/system/linux/zynqmp/zynqmp_amp_demo/ipi_shmem_demo.c index 3cc33e73..c5ef173f 100644 --- a/examples/system/linux/zynqmp/zynqmp_amp_demo/ipi_shmem_demo.c +++ b/examples/system/linux/zynqmp/zynqmp_amp_demo/ipi_shmem_demo.c @@ -97,19 +97,10 @@ static unsigned long long get_timestamp (void) static int ipi_irq_handler (int vect_id, void *priv) { (void)vect_id; - struct metal_io_region *ipi_io = (struct metal_io_region *)priv; - uint32_t ipi_mask = IPI_MASK; - uint64_t val = 1; - - if (!ipi_io) - return METAL_IRQ_NOT_HANDLED; - val = metal_io_read32(ipi_io, IPI_ISR_OFFSET); - if (val & ipi_mask) { - metal_io_write32(ipi_io, IPI_ISR_OFFSET, ipi_mask); - atomic_flag_clear(&remote_nkicked); - return METAL_IRQ_HANDLED; - } - return METAL_IRQ_NOT_HANDLED; + (void)priv; + + atomic_flag_clear(&remote_nkicked); + return METAL_IRQ_HANDLED; } /** @@ -124,13 +115,11 @@ static int ipi_irq_handler (int vect_id, void *priv) * * After all the packages are received, it sends out shutdown * message to the remote. * - * @param[in] ipi_io - IPI metal i/o region * @param[in] shm_io - shared memory metal i/o region * @return - return 0 on success, otherwise return error number indicating * type of error. */ -static int ipi_shmem_echo(struct metal_io_region *ipi_io, - struct metal_io_region *shm_io) +static int ipi_shmem_echo(struct metal_io_region *shm_io) { int ret; uint32_t i; @@ -144,7 +133,6 @@ static int ipi_shmem_echo(struct metal_io_region *ipi_io, long long tdiff_avg_s = 0, tdiff_avg_ns = 0; void *txbuf = NULL, *rxbuf = NULL, *tmpptr; struct msg_hdr_s *msg_hdr; - uint32_t ipi_mask = IPI_MASK; uint32_t tx_phy_addr_32; txbuf = metal_allocate_memory(BUF_SIZE_MAX); @@ -202,7 +190,7 @@ static int ipi_shmem_echo(struct metal_io_region *ipi_io, /* Increase number of available buffers */ metal_io_write32(shm_io, tx_avail_offset, (i + 1)); /* Kick IPI to notify data has been put to shared buffer */ - metal_io_write32(ipi_io, IPI_TRIG_OFFSET, ipi_mask); + kick_ipi(NULL); } LPRINTF("Waiting for messages to echo back and verify.\n"); @@ -303,7 +291,7 @@ static int ipi_shmem_echo(struct metal_io_region *ipi_io, metal_io_write32(shm_io, tx_addr_offset, tx_phy_addr_32); metal_io_write32(shm_io, tx_avail_offset, PKGS_TOTAL + 1); LPRINTF("Kick remote to notify shutdown message sent...\n"); - metal_io_write32(ipi_io, IPI_TRIG_OFFSET, ipi_mask); + kick_ipi(NULL); tdiff /= PKGS_TOTAL; tdiff_avg_s = tdiff / NS_PER_S; @@ -322,9 +310,8 @@ static int ipi_shmem_echo(struct metal_io_region *ipi_io, int ipi_shmem_demo() { - struct metal_device *ipi_dev = NULL, *shm_dev = NULL; - struct metal_io_region *ipi_io = NULL, *shm_io = NULL; - int ipi_irq; + struct metal_device *shm_dev = NULL; + struct metal_io_region *shm_io = NULL; int ret = 0; print_demo("IPI and shared memory"); @@ -344,51 +331,27 @@ int ipi_shmem_demo() goto out; } - /* Open IPI device */ - ret = metal_device_open(BUS_NAME, IPI_DEV_NAME, &ipi_dev); - if (ret) { - LPERROR("Failed to open device %s.\n", IPI_DEV_NAME); - goto out; - } - - /* Get IPI device IO region */ - ipi_io = metal_device_io_region(ipi_dev, 0); - if (!ipi_io) { - LPERROR("Failed to map io region for %s.\n", ipi_dev->name); - ret = -ENODEV; - goto out; - } - - /* Get the IPI IRQ from the opened IPI device */ - ipi_irq = (intptr_t)ipi_dev->irq_info; - - /* disable IPI interrupt */ - metal_io_write32(ipi_io, IPI_IDR_OFFSET, IPI_MASK); - /* clear old IPI interrupt */ - metal_io_write32(ipi_io, IPI_ISR_OFFSET, IPI_MASK); - /* Register IPI irq handler */ - metal_irq_register(ipi_irq, ipi_irq_handler, ipi_io); - metal_irq_enable(ipi_irq); /* initialize remote_nkicked */ remote_nkicked = (atomic_flag)ATOMIC_FLAG_INIT; atomic_flag_test_and_set(&remote_nkicked); - /* Enable IPI interrupt */ - metal_io_write32(ipi_io, IPI_IER_OFFSET, IPI_MASK); + + ret = init_ipi(); + if (ret) { + goto out; + } + ipi_kick_register_handler(ipi_irq_handler, NULL); + enable_ipi_kick(); /* Run atomic operation demo */ - ret = ipi_shmem_echo(ipi_io, shm_io); + ret = ipi_shmem_echo(shm_io); /* disable IPI interrupt */ - metal_io_write32(ipi_io, IPI_IDR_OFFSET, IPI_MASK); - /* unregister IPI irq handler by setting the handler to 0 */ - metal_irq_disable(ipi_irq); - metal_irq_unregister(ipi_irq); + disable_ipi_kick(); + deinit_ipi(); out: if (shm_dev) metal_device_close(shm_dev); - if (ipi_dev) - metal_device_close(ipi_dev); return ret; } diff --git a/examples/system/linux/zynqmp/zynqmp_amp_demo/shmem_atomic_demo.c b/examples/system/linux/zynqmp/zynqmp_amp_demo/shmem_atomic_demo.c index c650fe0c..017affb9 100644 --- a/examples/system/linux/zynqmp/zynqmp_amp_demo/shmem_atomic_demo.c +++ b/examples/system/linux/zynqmp/zynqmp_amp_demo/shmem_atomic_demo.c @@ -42,19 +42,9 @@ static atomic_flag remote_nkicked; /* is remote kicked, 0 - kicked, static int ipi_irq_handler (int vect_id, void *priv) { (void)vect_id; - struct metal_io_region *ipi_io = (struct metal_io_region *)priv; - uint32_t ipi_mask = IPI_MASK; - uint64_t val = 1; - - if (!ipi_io) - return METAL_IRQ_NOT_HANDLED; - val = metal_io_read32(ipi_io, IPI_ISR_OFFSET); - if (val & ipi_mask) { - metal_io_write32(ipi_io, IPI_ISR_OFFSET, ipi_mask); - atomic_flag_clear(&remote_nkicked); - return METAL_IRQ_HANDLED; - } - return METAL_IRQ_NOT_HANDLED; + (void)priv; + atomic_flag_clear(&remote_nkicked); + return METAL_IRQ_HANDLED; } /** @@ -69,17 +59,14 @@ static int ipi_irq_handler (int vect_id, void *priv) * if the value stored in the shared memory is the same as the * expected. * * It will print if the atomic add test has passed or not. - * @param[in] ipi_io - IPI metal i/o region * @param[in] shm_io - shared memory metal i/o region * @return - If setup failed, return the corresponding error number. Otherwise * return 0 on success. */ -static int atomic_add_shmem(struct metal_io_region *ipi_io, - struct metal_io_region *shm_io) +static int atomic_add_shmem(struct metal_io_region *shm_io) { int i, ret; atomic_int *shm_int; - uint32_t ipi_mask = IPI_MASK; LPRINTF("Starting atomic shared memory task.\n"); @@ -89,7 +76,7 @@ static int atomic_add_shmem(struct metal_io_region *ipi_io, atomic_store(shm_int, 0); /* Kick the remote to notify demo starts. */ - metal_io_write32(ipi_io, IPI_TRIG_OFFSET, ipi_mask); + kick_ipi(NULL); /* Do atomic add over the shared memory */ for (i = 0; i < ITERATIONS; i++) { @@ -113,9 +100,8 @@ static int atomic_add_shmem(struct metal_io_region *ipi_io, int atomic_shmem_demo() { - struct metal_device *ipi_dev = NULL, *shm_dev = NULL; - struct metal_io_region *ipi_io = NULL, *shm_io = NULL; - int ipi_irq; + struct metal_device *shm_dev = NULL; + struct metal_io_region *shm_io = NULL; int ret = 0; print_demo("atomic operation over shared memory"); @@ -135,51 +121,27 @@ int atomic_shmem_demo() goto out; } - /* Open IPI device */ - ret = metal_device_open(BUS_NAME, IPI_DEV_NAME, &ipi_dev); - if (ret) { - LPERROR("Failed to open device %s.\n", IPI_DEV_NAME); - goto out; - } - - /* Get IPI device IO region */ - ipi_io = metal_device_io_region(ipi_dev, 0); - if (!ipi_io) { - LPERROR("Failed to map io region for %s.\n", ipi_dev->name); - ret = -ENODEV; - goto out; - } - - /* Get the IPI IRQ from the opened IPI device */ - ipi_irq = (intptr_t)ipi_dev->irq_info; - - /* disable IPI interrupt */ - metal_io_write32(ipi_io, IPI_IDR_OFFSET, IPI_MASK); - /* clear old IPI interrupt */ - metal_io_write32(ipi_io, IPI_ISR_OFFSET, IPI_MASK); - /* Register IPI irq handler */ - metal_irq_register(ipi_irq, ipi_irq_handler, ipi_io); - metal_irq_enable(ipi_irq); /* initialize remote_nkicked */ remote_nkicked = (atomic_flag)ATOMIC_FLAG_INIT; atomic_flag_test_and_set(&remote_nkicked); - /* Enable IPI interrupt */ - metal_io_write32(ipi_io, IPI_IER_OFFSET, IPI_MASK); + + ret = init_ipi(); + if (ret) { + goto out; + } + ipi_kick_register_handler(ipi_irq_handler, NULL); + enable_ipi_kick(); /* Run atomic operation demo */ - ret = atomic_add_shmem(ipi_io, shm_io); + ret = atomic_add_shmem(shm_io); /* disable IPI interrupt */ - metal_io_write32(ipi_io, IPI_IDR_OFFSET, IPI_MASK); - /* unregister IPI irq handler by setting the handler to 0 */ - metal_irq_disable(ipi_irq); - metal_irq_unregister(ipi_irq); + disable_ipi_kick(); + deinit_ipi(); out: if (shm_dev) metal_device_close(shm_dev); - if (ipi_dev) - metal_device_close(ipi_dev); return ret; } diff --git a/examples/system/linux/zynqmp/zynqmp_amp_demo/shmem_latency_demo.c b/examples/system/linux/zynqmp/zynqmp_amp_demo/shmem_latency_demo.c index 256fa499..3133015a 100644 --- a/examples/system/linux/zynqmp/zynqmp_amp_demo/shmem_latency_demo.c +++ b/examples/system/linux/zynqmp/zynqmp_amp_demo/shmem_latency_demo.c @@ -58,13 +58,10 @@ #define PKG_SIZE_MAX 1024 struct channel_s { - struct metal_device *ipi_dev; /* IPI metal device */ - struct metal_io_region *ipi_io; /* IPI metal i/o region */ struct metal_device *shm_dev; /* Shared memory metal device */ struct metal_io_region *shm_io; /* Shared memory metal i/o region */ struct metal_device *ttc_dev; /* TTC metal device */ struct metal_io_region *ttc_io; /* TTC metal i/o region */ - uint32_t ipi_mask; /* RPU IPI mask */ atomic_flag remote_nkicked; /* 0 - kicked from remote */ }; @@ -141,18 +138,12 @@ static inline void stop_timer(struct metal_io_region *ttc_io, static int ipi_irq_handler (int vect_id, void *priv) { struct channel_s *ch = (struct channel_s *)priv; - uint32_t val; (void)vect_id; if (ch) { - val = metal_io_read32(ch->ipi_io, IPI_ISR_OFFSET); - if (val & ch->ipi_mask) { - metal_io_write32(ch->ipi_io, IPI_ISR_OFFSET, - ch->ipi_mask); - atomic_flag_clear(&ch->remote_nkicked); - return METAL_IRQ_HANDLED; - } + atomic_flag_clear(&ch->remote_nkicked); + return METAL_IRQ_HANDLED; } return METAL_IRQ_NOT_HANDLED; } @@ -212,8 +203,7 @@ static int measure_shmem_latency(struct channel_s *ch) goto out; } /* Kick IPI to notify the remote */ - metal_io_write32(ch->ipi_io, IPI_TRIG_OFFSET, - ch->ipi_mask); + kick_ipi(NULL); /* irq handler stops timer for rpu->apu irq */ wait_for_notified(&ch->remote_nkicked); /* Read message */ @@ -247,7 +237,7 @@ static int measure_shmem_latency(struct channel_s *ch) /* write to shared memory to indicate demo has finished */ metal_io_write32(ch->shm_io, SHM_DEMO_CNTRL_OFFSET, 0); /* Kick IPI to notify the remote */ - metal_io_write32(ch->ipi_io, IPI_TRIG_OFFSET, ch->ipi_mask); + kick_ipi(NULL); LPRINTF("Finished shared memory latency task\n"); @@ -261,7 +251,6 @@ int shmem_latency_demo() struct metal_device *dev; struct metal_io_region *io; struct channel_s ch; - int ipi_irq; int ret = 0; print_demo("shared memory latency"); @@ -301,56 +290,29 @@ int shmem_latency_demo() ch.ttc_dev = dev; ch.ttc_io = io; - /* Open IPI device */ - ret = metal_device_open(BUS_NAME, IPI_DEV_NAME, &dev); - if (ret) { - LPERROR("Failed to open device %s.\n", IPI_DEV_NAME); - goto out; - } - - /* Get IPI device IO region */ - io = metal_device_io_region(dev, 0); - if (!io) { - LPERROR("Failed to map io region for %s.\n", dev->name); - ret = -ENODEV; - goto out; - } - ch.ipi_dev = dev; - ch.ipi_io = io; - - /* Get the IPI IRQ from the opened IPI device */ - ipi_irq = (intptr_t)ch.ipi_dev->irq_info; - - /* disable IPI interrupt */ - metal_io_write32(ch.ipi_io, IPI_IDR_OFFSET, IPI_MASK); - /* clear old IPI interrupt */ - metal_io_write32(ch.ipi_io, IPI_ISR_OFFSET, IPI_MASK); /* initialize remote_nkicked */ ch.remote_nkicked = (atomic_flag)ATOMIC_FLAG_INIT; atomic_flag_test_and_set(&ch.remote_nkicked); - ch.ipi_mask = IPI_MASK; - /* Register IPI irq handler */ - metal_irq_register(ipi_irq, ipi_irq_handler, &ch); - metal_irq_enable(ipi_irq); - /* Enable IPI interrupt */ - metal_io_write32(ch.ipi_io, IPI_IER_OFFSET, IPI_MASK); + + ret = init_ipi(); + if (ret) { + goto out; + } + ipi_kick_register_handler(ipi_irq_handler, &ch); + enable_ipi_kick(); /* Run atomic operation demo */ ret = measure_shmem_latency(&ch); /* disable IPI interrupt */ - metal_io_write32(ch.ipi_io, IPI_IDR_OFFSET, IPI_MASK); - /* unregister IPI irq handler by setting the handler to 0 */ - metal_irq_disable(ipi_irq); - metal_irq_unregister(ipi_irq); + disable_ipi_kick(); + deinit_ipi(); out: if (ch.ttc_dev) metal_device_close(ch.ttc_dev); if (ch.shm_dev) metal_device_close(ch.shm_dev); - if (ch.ipi_dev) - metal_device_close(ch.ipi_dev); return ret; } diff --git a/examples/system/linux/zynqmp/zynqmp_amp_demo/shmem_throughput_demo.c b/examples/system/linux/zynqmp/zynqmp_amp_demo/shmem_throughput_demo.c index 941ed55f..a5ff9482 100644 --- a/examples/system/linux/zynqmp/zynqmp_amp_demo/shmem_throughput_demo.c +++ b/examples/system/linux/zynqmp/zynqmp_amp_demo/shmem_throughput_demo.c @@ -76,13 +76,10 @@ #define MB (1024 * 1024) /* Mega Bytes */ struct channel_s { - struct metal_device *ipi_dev; /* IPI metal device */ - struct metal_io_region *ipi_io; /* IPI metal i/o region */ struct metal_device *shm_dev; /* Shared memory metal device */ struct metal_io_region *shm_io; /* Shared memory metal i/o region */ struct metal_device *ttc_dev; /* TTC metal device */ struct metal_io_region *ttc_io; /* TTC metal i/o region */ - uint32_t ipi_mask; /* RPU IPI mask */ atomic_flag remote_nkicked; /* 0 - kicked from remote */ }; @@ -154,18 +151,12 @@ static inline void stop_timer(struct metal_io_region *ttc_io, static int ipi_irq_handler (int vect_id, void *priv) { struct channel_s *ch = (struct channel_s *)priv; - uint32_t val; (void)vect_id; if (ch) { - val = metal_io_read32(ch->ipi_io, IPI_ISR_OFFSET); - if (val & ch->ipi_mask) { - metal_io_write32(ch->ipi_io, IPI_ISR_OFFSET, - ch->ipi_mask); - atomic_flag_clear(&ch->remote_nkicked); - return METAL_IRQ_HANDLED; - } + atomic_flag_clear(&ch->remote_nkicked); + return METAL_IRQ_HANDLED; } return METAL_IRQ_NOT_HANDLED; } @@ -264,8 +255,7 @@ static int measure_shmem_throughput(struct channel_s* ch) tx_count); /* Kick IPI to notify RPU data is ready in * the shared memory */ - metal_io_write32(ch->ipi_io, IPI_TRIG_OFFSET, - ch->ipi_mask); + kick_ipi(NULL); } /* Stop RPU TTC counter */ stop_timer(ch->ttc_io, TTC_CNT_APU_TO_RPU); @@ -279,7 +269,7 @@ static int measure_shmem_throughput(struct channel_s* ch) /* Kick IPI to notify RPU that APU has read the RPU RX TTC counter * value */ - metal_io_write32(ch->ipi_io, IPI_TRIG_OFFSET, ch->ipi_mask); + kick_ipi(NULL); /* for each data size, meaasure block read throughput */ for (s = PKG_SIZE_MIN, i = 0; s <= PKG_SIZE_MAX; s <<= 1, i++) { @@ -332,7 +322,7 @@ static int measure_shmem_throughput(struct channel_s* ch) atomic_flag_clear(&ch->remote_nkicked); atomic_flag_test_and_set(&ch->remote_nkicked); /* Kick IPI to notify remote it is ready to read data */ - metal_io_write32(ch->ipi_io, IPI_TRIG_OFFSET, ch->ipi_mask); + kick_ipi(NULL); /* Wait for RPU to signal RPU TX TTC counter is ready to * read */ wait_for_notified(&ch->remote_nkicked); @@ -341,7 +331,7 @@ static int measure_shmem_throughput(struct channel_s* ch) rpu_tx_count[i] = read_timer(ch->ttc_io, TTC_CNT_RPU_TO_APU); /* Kick IPI to notify RPU APU has read the RPU TX TTC counter * value */ - metal_io_write32(ch->ipi_io, IPI_TRIG_OFFSET, ch->ipi_mask); + kick_ipi(NULL); } /* Print the measurement result */ @@ -378,7 +368,6 @@ int shmem_throughput_demo() struct metal_device *dev; struct metal_io_region *io; struct channel_s ch; - int ipi_irq; int ret = 0; print_demo("shared memory throughput"); @@ -418,56 +407,29 @@ int shmem_throughput_demo() ch.ttc_dev = dev; ch.ttc_io = io; - /* Open IPI device */ - ret = metal_device_open(BUS_NAME, IPI_DEV_NAME, &dev); - if (ret) { - LPERROR("Failed to open device %s.\n", IPI_DEV_NAME); - goto out; - } - - /* Get IPI device IO region */ - io = metal_device_io_region(dev, 0); - if (!io) { - LPERROR("Failed to map io region for %s.\n", dev->name); - ret = -ENODEV; - goto out; - } - ch.ipi_dev = dev; - ch.ipi_io = io; - - /* Get the IPI IRQ from the opened IPI device */ - ipi_irq = (intptr_t)ch.ipi_dev->irq_info; - - /* disable IPI interrupt */ - metal_io_write32(ch.ipi_io, IPI_IDR_OFFSET, IPI_MASK); - /* clear old IPI interrupt */ - metal_io_write32(ch.ipi_io, IPI_ISR_OFFSET, IPI_MASK); /* initialize remote_nkicked */ ch.remote_nkicked = (atomic_flag)ATOMIC_FLAG_INIT; atomic_flag_test_and_set(&ch.remote_nkicked); - ch.ipi_mask = IPI_MASK; - /* Register IPI irq handler */ - metal_irq_register(ipi_irq, ipi_irq_handler, &ch); - metal_irq_enable(ipi_irq); - /* Enable IPI interrupt */ - metal_io_write32(ch.ipi_io, IPI_IER_OFFSET, IPI_MASK); + + ret = init_ipi(); + if (ret) { + goto out; + } + ipi_kick_register_handler(ipi_irq_handler, &ch); + enable_ipi_kick(); /* Run atomic operation demo */ ret = measure_shmem_throughput(&ch); /* disable IPI interrupt */ - metal_io_write32(ch.ipi_io, IPI_IDR_OFFSET, IPI_MASK); - /* unregister IPI irq handler by setting the handler to 0 */ - metal_irq_disable(ipi_irq); - metal_irq_unregister(ipi_irq); + disable_ipi_kick(); + deinit_ipi(); out: if (ch.ttc_dev) metal_device_close(ch.ttc_dev); if (ch.shm_dev) metal_device_close(ch.shm_dev); - if (ch.ipi_dev) - metal_device_close(ch.ipi_dev); return ret; }