diff options
Diffstat (limited to 'kernel/ethosu_device.c')
-rw-r--r-- | kernel/ethosu_device.c | 259 |
1 files changed, 128 insertions, 131 deletions
diff --git a/kernel/ethosu_device.c b/kernel/ethosu_device.c index 36b776f..004b26f 100644 --- a/kernel/ethosu_device.c +++ b/kernel/ethosu_device.c @@ -25,7 +25,7 @@ #include "ethosu_device.h" #include "ethosu_buffer.h" -#include "ethosu_core_interface.h" +#include "ethosu_core_rpmsg.h" #include "ethosu_capabilities.h" #include "ethosu_inference.h" #include "ethosu_cancel_inference.h" @@ -46,102 +46,98 @@ * Defines ****************************************************************************/ -#define DMA_ADDR_BITS 32 /* Number of address bits */ - /**************************************************************************** * Functions ****************************************************************************/ /* Incoming messages */ -static int ethosu_handle_msg(struct ethosu_device *edev) +static int ethosu_handle_msg(struct rpmsg_device *rpdev, + void *data, + int len, + void *priv, + u32 src) { + struct ethosu_device *edev = dev_get_drvdata(&rpdev->dev); + struct device *dev = &rpdev->dev; + struct ethosu_core_rpmsg *rpmsg = data; + int length = len - sizeof(rpmsg->header); int ret; - struct ethosu_core_msg header; - - union { - struct ethosu_core_msg_err error; - struct ethosu_core_inference_rsp inf; - struct ethosu_core_msg_version version; - struct ethosu_core_msg_capabilities_rsp capabilities; - struct ethosu_core_network_info_rsp network_info; - struct ethosu_core_cancel_inference_rsp cancellation; - } data; - - /* Read message */ - ret = ethosu_mailbox_read(&edev->mailbox, &header, &data, sizeof(data)); - if (ret) - return ret; - switch (header.type) { + dev_info(dev, + "Msg: magic=0x%08x, type=%u, msg_id=%llu", + rpmsg->header.magic, rpmsg->header.type, rpmsg->header.msg_id); + + switch (rpmsg->header.type) { case ETHOSU_CORE_MSG_ERR: - if (header.length != sizeof(data.error)) { - dev_warn(edev->dev, - "Msg: Error message of incorrect size. size=%u, expected=%zu\n", header.length, - sizeof(data.error)); + if (length != sizeof(rpmsg->error)) { + dev_warn(dev, + "Msg: Error message of incorrect size. size=%u, expected=%zu", length, + sizeof(rpmsg->error)); ret = -EBADMSG; break; } - data.error.msg[sizeof(data.error.msg) - 1] = '\0'; - dev_warn(edev->dev, "Msg: Error. type=%u, msg=\"%s\"\n", - data.error.type, data.error.msg); + rpmsg->error.msg[sizeof(rpmsg->error.msg) - 1] = '\0'; + dev_warn(dev, "Msg: Error. type=%u, msg=\"%s\"", + rpmsg->error.type, rpmsg->error.msg); ret = -EBADMSG; break; case ETHOSU_CORE_MSG_PING: - dev_info(edev->dev, "Msg: Ping\n"); + dev_info(dev, "Msg: Ping"); ret = ethosu_mailbox_pong(&edev->mailbox); break; case ETHOSU_CORE_MSG_PONG: - dev_info(edev->dev, "Msg: Pong\n"); + dev_info(dev, "Msg: Pong"); break; case ETHOSU_CORE_MSG_INFERENCE_RSP: - if (header.length != sizeof(data.inf)) { - dev_warn(edev->dev, - "Msg: Inference response of incorrect size. size=%u, expected=%zu\n", header.length, - sizeof(data.inf)); + if (length != sizeof(rpmsg->inf_rsp)) { + dev_warn(dev, + "Msg: Inference response of incorrect size. size=%u, expected=%zu", length, + sizeof(rpmsg->inf_rsp)); ret = -EBADMSG; break; } - dev_info(edev->dev, - "Msg: Inference response. user_arg=0x%llx, ofm_count=%u, status=%u\n", - data.inf.user_arg, data.inf.ofm_count, - data.inf.status); + dev_info(dev, + "Msg: Inference response. ofm_count=%u, status=%u", + rpmsg->inf_rsp.ofm_count, rpmsg->inf_rsp.status); - ethosu_inference_rsp(edev, &data.inf); + ethosu_inference_rsp(edev, rpmsg->header.msg_id, + &rpmsg->inf_rsp); break; case ETHOSU_CORE_MSG_CANCEL_INFERENCE_RSP: - if (header.length != sizeof(data.cancellation)) { - dev_warn(edev->dev, - "Msg: Cancel Inference response of incorrect size. size=%u, expected=%zu\n", header.length, - sizeof(data.cancellation)); + if (length != sizeof(rpmsg->cancel_rsp)) { + dev_warn(dev, + "Msg: Cancel Inference response of incorrect size. size=%u, expected=%zu", length, + sizeof(rpmsg->cancel_rsp)); ret = -EBADMSG; break; } - dev_info(edev->dev, - "Msg: Cancel Inference response. user_arg=0x%llx, status=%u\n", - data.cancellation.user_arg, data.cancellation.status); - ethosu_cancel_inference_rsp(edev, &data.cancellation); + dev_info(dev, + "Msg: Cancel Inference response. status=%u", + rpmsg->cancel_rsp.status); + ethosu_cancel_inference_rsp(edev, rpmsg->header.msg_id, + &rpmsg->cancel_rsp); break; case ETHOSU_CORE_MSG_VERSION_RSP: - if (header.length != sizeof(data.version)) { - dev_warn(edev->dev, - "Msg: Version response of incorrect size. size=%u, expected=%zu\n", header.length, - sizeof(data.version)); + if (length != sizeof(rpmsg->version_rsp)) { + dev_warn(dev, + "Msg: Version response of incorrect size. size=%u, expected=%zu", length, + sizeof(rpmsg->version_rsp)); ret = -EBADMSG; break; } - dev_info(edev->dev, "Msg: Version response v%u.%u.%u\n", - data.version.major, data.version.minor, - data.version.patch); + dev_info(dev, "Msg: Version response v%u.%u.%u", + rpmsg->version_rsp.major, rpmsg->version_rsp.minor, + rpmsg->version_rsp.patch); /* Check major and minor version match, else return error */ - if (data.version.major != ETHOSU_CORE_MSG_VERSION_MAJOR || - data.version.minor != ETHOSU_CORE_MSG_VERSION_MINOR) { - dev_warn(edev->dev, "Msg: Version mismatch detected! "); - dev_warn(edev->dev, "Local version: v%u.%u.%u\n", + if (rpmsg->version_rsp.major != ETHOSU_CORE_MSG_VERSION_MAJOR || + rpmsg->version_rsp.minor != ETHOSU_CORE_MSG_VERSION_MINOR) { + dev_warn(dev, "Msg: Version mismatch detected! "); + dev_warn(dev, "Local version: v%u.%u.%u", ETHOSU_CORE_MSG_VERSION_MAJOR, ETHOSU_CORE_MSG_VERSION_MINOR, ETHOSU_CORE_MSG_VERSION_PATCH); @@ -149,53 +145,54 @@ static int ethosu_handle_msg(struct ethosu_device *edev) break; case ETHOSU_CORE_MSG_CAPABILITIES_RSP: - if (header.length != sizeof(data.capabilities)) { - dev_warn(edev->dev, - "Msg: Capabilities response of incorrect size. size=%u, expected=%zu\n", header.length, - sizeof(data.capabilities)); + if (length != sizeof(rpmsg->cap_rsp)) { + dev_warn(dev, + "Msg: Capabilities response of incorrect size. size=%u, expected=%zu", length, + sizeof(rpmsg->cap_rsp)); ret = -EBADMSG; break; } - dev_info(edev->dev, - "Msg: Capabilities response ua%llx vs%hhu v%hhu.%hhu p%hhu av%hhu.%hhu.%hhu dv%hhu.%hhu.%hhu mcc%hhu csv%hhu cd%hhu\n", - data.capabilities.user_arg, - data.capabilities.version_status, - data.capabilities.version_major, - data.capabilities.version_minor, - data.capabilities.product_major, - data.capabilities.arch_major_rev, - data.capabilities.arch_minor_rev, - data.capabilities.arch_patch_rev, - data.capabilities.driver_major_rev, - data.capabilities.driver_minor_rev, - data.capabilities.driver_patch_rev, - data.capabilities.macs_per_cc, - data.capabilities.cmd_stream_version, - data.capabilities.custom_dma); - - ethosu_capability_rsp(edev, &data.capabilities); + dev_info(dev, + "Msg: Capabilities response vs%hhu v%hhu.%hhu p%hhu av%hhu.%hhu.%hhu dv%hhu.%hhu.%hhu mcc%hhu csv%hhu cd%hhu", + rpmsg->cap_rsp.version_status, + rpmsg->cap_rsp.version_major, + rpmsg->cap_rsp.version_minor, + rpmsg->cap_rsp.product_major, + rpmsg->cap_rsp.arch_major_rev, + rpmsg->cap_rsp.arch_minor_rev, + rpmsg->cap_rsp.arch_patch_rev, + rpmsg->cap_rsp.driver_major_rev, + rpmsg->cap_rsp.driver_minor_rev, + rpmsg->cap_rsp.driver_patch_rev, + rpmsg->cap_rsp.macs_per_cc, + rpmsg->cap_rsp.cmd_stream_version, + rpmsg->cap_rsp.custom_dma); + + ethosu_capability_rsp(edev, rpmsg->header.msg_id, + &rpmsg->cap_rsp); break; case ETHOSU_CORE_MSG_NETWORK_INFO_RSP: - if (header.length != sizeof(data.network_info)) { - dev_warn(edev->dev, - "Msg: Network info response of incorrect size. size=%u, expected=%zu\n", header.length, - sizeof(data.network_info)); + if (length != sizeof(rpmsg->net_info_rsp)) { + dev_warn(dev, + "Msg: Network info response of incorrect size. size=%u, expected=%zu", length, + sizeof(rpmsg->net_info_rsp)); ret = -EBADMSG; break; } - dev_info(edev->dev, - "Msg: Network info response. user_arg=0x%llx, status=%u", - data.network_info.user_arg, - data.network_info.status); + dev_info(dev, + "Msg: Network info response. status=%u", + rpmsg->net_info_rsp.status); - ethosu_network_info_rsp(edev, &data.network_info); + ethosu_network_info_rsp(edev, rpmsg->header.msg_id, + &rpmsg->net_info_rsp); break; default: /* This should not happen due to version checks */ - dev_warn(edev->dev, "Msg: Protocol error\n"); + dev_warn(dev, "Msg: Protocol error. type=%u", + rpmsg->header.type); ret = -EPROTO; break; } @@ -211,7 +208,7 @@ static int ethosu_open(struct inode *inode, file->private_data = edev; - dev_info(edev->dev, "Device open. file=0x%pK\n", file); + dev_info(edev->dev, "Device open. file=0x%pK", file); return nonseekable_open(inode, file); } @@ -228,19 +225,19 @@ static long ethosu_ioctl(struct file *file, if (ret) return ret; - dev_info(edev->dev, "Device ioctl. file=0x%pK, cmd=0x%x, arg=0x%lx\n", + dev_info(edev->dev, "Device ioctl. file=0x%pK, cmd=0x%x, arg=0x%lx", file, cmd, arg); switch (cmd) { case ETHOSU_IOCTL_VERSION_REQ: - dev_info(edev->dev, "Device ioctl: Send version request\n"); + dev_info(edev->dev, "Device ioctl: Send version request"); ret = ethosu_mailbox_version_request(&edev->mailbox); break; case ETHOSU_IOCTL_CAPABILITIES_REQ: { struct ethosu_uapi_device_capabilities uapi; dev_info(edev->dev, - "Device ioctl: Send capabilities request\n"); + "Device ioctl: Send capabilities request"); ret = ethosu_capabilities_request(edev, &uapi); if (ret) @@ -250,7 +247,7 @@ static long ethosu_ioctl(struct file *file, break; } case ETHOSU_IOCTL_PING: { - dev_info(edev->dev, "Device ioctl: Send ping\n"); + dev_info(edev->dev, "Device ioctl: Send ping"); ret = ethosu_mailbox_ping(&edev->mailbox); break; } @@ -261,7 +258,7 @@ static long ethosu_ioctl(struct file *file, break; dev_info(edev->dev, - "Device ioctl: Buffer create. capacity=%u\n", + "Device ioctl: Buffer create. capacity=%u", uapi.capacity); ret = ethosu_buffer_create(edev, uapi.capacity); @@ -274,7 +271,7 @@ static long ethosu_ioctl(struct file *file, break; dev_info(edev->dev, - "Device ioctl: Network create. type=%u, fd/index=%u\n", + "Device ioctl: Network create. type=%u, fd/index=%u", uapi.type, uapi.fd); ret = ethosu_network_create(edev, &uapi); @@ -292,31 +289,34 @@ static long ethosu_ioctl(struct file *file, return ret; } -static void ethosu_mbox_rx(void *user_arg) +static struct rpmsg_endpoint *ethosu_create_ept(struct rpmsg_device *rpdev) { - struct ethosu_device *edev = user_arg; - int ret; + struct device *dev = &rpdev->dev; + struct rpmsg_channel_info info; + struct rpmsg_endpoint *ept; - mutex_lock(&edev->mutex); + /* Create rpmsg endpoint */ + strncpy(info.name, rpdev->id.name, sizeof(info.name)); + info.src = 0; + info.dst = rpdev->dst; - do { - ret = ethosu_handle_msg(edev); - if (ret && ret != -ENOMSG) - /* Need to start over in case of error, empty the queue - * by fast-forwarding read position to write position. - * */ - ethosu_mailbox_reset(&edev->mailbox); - } while (ret == 0); + dev_info(dev, "Creating rpmsg endpoint. name=%s, src=%u, dst=%u", + info.name, info.src, info.dst); - mutex_unlock(&edev->mutex); + ept = rpmsg_create_ept(rpdev, ethosu_handle_msg, NULL, info); + if (!ept) { + dev_err(&rpdev->dev, "Failed to create endpoint"); + + return ERR_PTR(-EINVAL); + } + + return ept; } int ethosu_dev_init(struct ethosu_device *edev, - struct device *dev, + struct rpmsg_device *rpdev, struct class *class, - dev_t devt, - struct resource *in_queue, - struct resource *out_queue) + dev_t devt) { static const struct file_operations fops = { .owner = THIS_MODULE, @@ -329,43 +329,43 @@ int ethosu_dev_init(struct ethosu_device *edev, struct device *sysdev; int ret; - edev->dev = dev; + edev->dev = &rpdev->dev; + edev->rpdev = rpdev; edev->class = class; edev->devt = devt; mutex_init(&edev->mutex); - ret = of_reserved_mem_device_init(edev->dev); - if (ret) - return ret; - - dma_set_mask_and_coherent(edev->dev, DMA_BIT_MASK(DMA_ADDR_BITS)); + edev->ept = ethosu_create_ept(rpdev); + if (IS_ERR(edev->ept)) + return PTR_ERR(edev->ept); - ret = ethosu_mailbox_init(&edev->mailbox, dev, in_queue, out_queue, - ethosu_mbox_rx, edev); + ret = ethosu_mailbox_init(&edev->mailbox, edev->dev, edev->ept); if (ret) - goto release_reserved_mem; + return ret; cdev_init(&edev->cdev, &fops); edev->cdev.owner = THIS_MODULE; ret = cdev_add(&edev->cdev, edev->devt, 1); if (ret) { - dev_err(edev->dev, "Failed to add character device.\n"); + dev_err(edev->dev, "Failed to add character device."); goto deinit_mailbox; } sysdev = device_create(edev->class, NULL, edev->devt, edev, "ethosu%d", MINOR(edev->devt)); if (IS_ERR(sysdev)) { - dev_err(edev->dev, "Failed to create device.\n"); + dev_err(edev->dev, "Failed to create device."); ret = PTR_ERR(sysdev); goto del_cdev; } dev_info(edev->dev, - "Created Arm Ethos-U device. name=%s, major=%d, minor=%d\n", + "Created Arm Ethos-U device. name=%s, major=%d, minor=%d", dev_name(sysdev), MAJOR(edev->devt), MINOR(edev->devt)); + ethosu_mailbox_ping(&edev->mailbox); + return 0; del_cdev: @@ -374,18 +374,15 @@ del_cdev: deinit_mailbox: ethosu_mailbox_deinit(&edev->mailbox); -release_reserved_mem: - of_reserved_mem_device_release(edev->dev); - return ret; } void ethosu_dev_deinit(struct ethosu_device *edev) { + dev_info(edev->dev, "%s\n", __FUNCTION__); + ethosu_mailbox_deinit(&edev->mailbox); + rpmsg_destroy_ept(edev->ept); device_destroy(edev->class, edev->cdev.dev); cdev_del(&edev->cdev); - of_reserved_mem_device_release(edev->dev); - - dev_info(edev->dev, "%s\n", __FUNCTION__); } |