diff options
author | Davide Grohmann <davide.grohmann@arm.com> | 2021-06-01 15:03:51 +0200 |
---|---|---|
committer | Kristofer Jonsson <kristofer.jonsson@arm.com> | 2021-06-10 14:58:49 +0000 |
commit | 35ce6c809ccf637c6bb8a00ad14b051b87d9884a (patch) | |
tree | e999250ca985ac5b00ba9162ee1782de02983c03 /kernel | |
parent | 0c79f896caf1a0ac16dd92810c4b15bfff00bdb3 (diff) | |
download | ethos-u-linux-driver-stack-35ce6c809ccf637c6bb8a00ad14b051b87d9884a.tar.gz |
Add support for handling capabilities requests
Change-Id: Id5aa197312c88b0c448dc085d8477ed67da24724
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/ethosu_core_interface.h | 30 | ||||
-rw-r--r-- | kernel/ethosu_device.c | 166 | ||||
-rw-r--r-- | kernel/ethosu_device.h | 14 | ||||
-rw-r--r-- | kernel/ethosu_mailbox.c | 12 | ||||
-rw-r--r-- | kernel/ethosu_mailbox.h | 8 | ||||
-rw-r--r-- | kernel/uapi/ethosu.h | 51 |
6 files changed, 278 insertions, 3 deletions
diff --git a/kernel/ethosu_core_interface.h b/kernel/ethosu_core_interface.h index 4e7a864..ad8311c 100644 --- a/kernel/ethosu_core_interface.h +++ b/kernel/ethosu_core_interface.h @@ -55,6 +55,8 @@ enum ethosu_core_msg_type { ETHOSU_CORE_MSG_INFERENCE_RSP, ETHOSU_CORE_MSG_VERSION_REQ, ETHOSU_CORE_MSG_VERSION_RSP, + ETHOSU_CORE_MSG_CAPABILITIES_REQ, + ETHOSU_CORE_MSG_CAPABILITIES_RSP, ETHOSU_CORE_MSG_MAX }; @@ -129,6 +131,34 @@ struct ethosu_core_msg_version { }; /** + * struct ethosu_core_capabilities_req - Message capabilities request + */ +struct ethosu_core_capabilities_req { + uint64_t user_arg; +}; + +/** + * struct ethosu_core_capabilities_rsp - Message capabilities response + */ +struct ethosu_core_msg_capabilities_rsp { + uint64_t user_arg; + uint32_t version_status; + uint32_t version_minor; + uint32_t version_major; + uint32_t product_major; + uint32_t arch_patch_rev; + uint32_t arch_minor_rev; + uint32_t arch_major_rev; + uint32_t driver_patch_rev; + uint32_t driver_minor_rev; + uint32_t driver_major_rev; + uint32_t macs_per_cc; + uint32_t cmd_stream_version; + uint32_t shram_size; + uint32_t custom_dma; +}; + +/** * enum ethosu_core_msg_err_type - Error types */ enum ethosu_core_msg_err_type { diff --git a/kernel/ethosu_device.c b/kernel/ethosu_device.c index e82b4c0..7adc7a6 100644 --- a/kernel/ethosu_device.c +++ b/kernel/ethosu_device.c @@ -38,6 +38,7 @@ #include <linux/io.h> #include <linux/of_reserved_mem.h> #include <linux/uaccess.h> +#include <linux/slab.h> /**************************************************************************** * Defines @@ -47,6 +48,8 @@ #define MINOR_COUNT 1 /* Allocate 1 minor version */ #define DMA_ADDR_BITS 32 /* Number of address bits */ +#define CAPABILITIES_RESP_TIMEOUT_MS 50 + /**************************************************************************** * Types ****************************************************************************/ @@ -55,6 +58,71 @@ * Functions ****************************************************************************/ +static void ethosu_capabilities_destroy(struct kref *kref) +{ + struct ethosu_capabilities *cap = + container_of(kref, struct ethosu_capabilities, refcount); + + list_del(&cap->list); + + devm_kfree(cap->edev->dev, cap); +} + +static int ethosu_capabilities_find(struct ethosu_capabilities *cap, + struct list_head *capabilties_list) +{ + struct ethosu_capabilities *cur; + + list_for_each_entry(cur, capabilties_list, list) { + if (cur == cap) + return 0; + } + + return -EINVAL; +} + +static int ethosu_capability_rsp(struct ethosu_device *edev, + struct ethosu_core_msg_capabilities_rsp *msg) +{ + struct ethosu_capabilities *cap; + struct ethosu_uapi_device_capabilities *capabilities; + int ret; + + cap = (struct ethosu_capabilities *)msg->user_arg; + ret = ethosu_capabilities_find(cap, &edev->capabilities_list); + if (0 != ret) { + dev_warn(edev->dev, + "Handle not found in capabilities list. handle=0x%p\n", + cap); + + /* NOTE: do not call complete or kref_put on invalid data! */ + return ret; + } + + capabilities = cap->capabilities; + + capabilities->hw_id.version_status = msg->version_status; + capabilities->hw_id.version_minor = msg->version_minor; + capabilities->hw_id.version_major = msg->version_major; + capabilities->hw_id.product_major = msg->product_major; + capabilities->hw_id.arch_patch_rev = msg->arch_patch_rev; + capabilities->hw_id.arch_minor_rev = msg->arch_minor_rev; + capabilities->hw_id.arch_major_rev = msg->arch_major_rev; + capabilities->driver_patch_rev = msg->driver_patch_rev; + capabilities->driver_minor_rev = msg->driver_minor_rev; + capabilities->driver_major_rev = msg->driver_major_rev; + capabilities->hw_cfg.macs_per_cc = msg->macs_per_cc; + capabilities->hw_cfg.cmd_stream_version = msg->cmd_stream_version; + capabilities->hw_cfg.shram_size = msg->shram_size; + capabilities->hw_cfg.custom_dma = msg->custom_dma; + + complete(&cap->done); + + kref_put(&cap->refcount, ethosu_capabilities_destroy); + + return 0; +} + /* Incoming messages */ static int ethosu_handle_msg(struct ethosu_device *edev) { @@ -62,9 +130,10 @@ static int ethosu_handle_msg(struct ethosu_device *edev) 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_err error; + struct ethosu_core_inference_rsp inf; + struct ethosu_core_msg_version version; + struct ethosu_core_msg_capabilities_rsp capabilities; } data; /* Read message */ @@ -133,7 +202,35 @@ 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)); + 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 ss%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.shram_size, + data.capabilities.custom_dma); + + ret = ethosu_capability_rsp(edev, &data.capabilities); + break; default: /* This should not happen due to version checks */ dev_warn(edev->dev, "Msg: Protocol error\n"); @@ -157,6 +254,64 @@ static int ethosu_open(struct inode *inode, return nonseekable_open(inode, file); } +static int ethosu_send_capabilities_request(struct ethosu_device *edev, + void __user *udata) +{ + struct ethosu_uapi_device_capabilities uapi; + struct ethosu_capabilities *cap; + int ret; + int timeout; + + cap = devm_kzalloc(edev->dev, sizeof(struct ethosu_capabilities), + GFP_KERNEL); + if (!cap) + return -ENOMEM; + + cap->edev = edev; + cap->capabilities = &uapi; + kref_init(&cap->refcount); + init_completion(&cap->done); + list_add(&cap->list, &edev->capabilities_list); + + ret = ethosu_mailbox_capabilities_request(&edev->mailbox, cap); + if (0 != ret) + goto put_kref; + + /* + * Increase ref counter since we sent the pointer out to + * response handler thread. That thread is responsible to + * decrease the ref counter before exiting. So the memory + * can be freed. + * + * NOTE: if no response is received back, the memory is leaked. + */ + kref_get(&cap->refcount); + /* Unlock the mutex before going to block on the condition */ + mutex_unlock(&edev->mutex); + /* wait for response to arrive back */ + timeout = wait_for_completion_timeout(&cap->done, + msecs_to_jiffies( + CAPABILITIES_RESP_TIMEOUT_MS)); + /* take back the mutex before resuming to do anything */ + ret = mutex_lock_interruptible(&edev->mutex); + if (0 != ret) + goto put_kref; + + if (0 == timeout /* timed out*/) { + dev_warn(edev->dev, + "Msg: Capabilities response lost - timeout\n"); + ret = -EIO; + goto put_kref; + } + + ret = copy_to_user(udata, &uapi, sizeof(uapi)) ? -EFAULT : 0; + +put_kref: + kref_put(&cap->refcount, ethosu_capabilities_destroy); + + return ret; +} + static long ethosu_ioctl(struct file *file, unsigned int cmd, unsigned long arg) @@ -176,6 +331,10 @@ static long ethosu_ioctl(struct file *file, dev_info(edev->dev, "Ioctl: Send version request\n"); ret = ethosu_mailbox_version_request(&edev->mailbox); break; + case ETHOSU_IOCTL_CAPABILITIES_REQ: + dev_info(edev->dev, "Ioctl: Send capabilities request\n"); + ret = ethosu_send_capabilities_request(edev, udata); + break; case ETHOSU_IOCTL_PING: { dev_info(edev->dev, "Ioctl: Send ping\n"); ret = ethosu_mailbox_ping(&edev->mailbox); @@ -257,6 +416,7 @@ int ethosu_dev_init(struct ethosu_device *edev, edev->dev = dev; edev->class = class; mutex_init(&edev->mutex); + INIT_LIST_HEAD(&edev->capabilities_list); INIT_LIST_HEAD(&edev->inference_list); ret = of_reserved_mem_device_init(edev->dev); diff --git a/kernel/ethosu_device.h b/kernel/ethosu_device.h index 4e4f59d..0722814 100644 --- a/kernel/ethosu_device.h +++ b/kernel/ethosu_device.h @@ -25,6 +25,7 @@ * Includes ****************************************************************************/ +#include "uapi/ethosu.h" #include "ethosu_mailbox.h" #include <linux/device.h> @@ -32,6 +33,7 @@ #include <linux/io.h> #include <linux/mutex.h> #include <linux/workqueue.h> +#include <linux/completion.h> /**************************************************************************** * Types @@ -47,9 +49,21 @@ struct ethosu_device { dev_t devt; struct mutex mutex; struct ethosu_mailbox mailbox; + struct list_head capabilities_list; struct list_head inference_list; }; +/** + * struct ethosu_capabilities - Capabilities internal struct + */ +struct ethosu_capabilities { + struct ethosu_device *edev; + struct completion done; + struct kref refcount; + struct ethosu_uapi_device_capabilities *capabilities; + struct list_head list; +}; + /**************************************************************************** * Functions ****************************************************************************/ diff --git a/kernel/ethosu_mailbox.c b/kernel/ethosu_mailbox.c index f61c181..158a7f5 100644 --- a/kernel/ethosu_mailbox.c +++ b/kernel/ethosu_mailbox.c @@ -213,6 +213,18 @@ int ethosu_mailbox_version_request(struct ethosu_mailbox *mbox) 0); } +int ethosu_mailbox_capabilities_request(struct ethosu_mailbox *mbox, + void *user_arg) +{ + struct ethosu_core_capabilities_req req = { + .user_arg = (ptrdiff_t)user_arg + }; + + return ethosu_queue_write_msg(mbox, ETHOSU_CORE_MSG_CAPABILITIES_REQ, + &req, + sizeof(req)); +} + int ethosu_mailbox_inference(struct ethosu_mailbox *mbox, void *user_arg, uint32_t ifm_count, diff --git a/kernel/ethosu_mailbox.h b/kernel/ethosu_mailbox.h index 0bc5ffb..5cd5e62 100644 --- a/kernel/ethosu_mailbox.h +++ b/kernel/ethosu_mailbox.h @@ -114,6 +114,14 @@ int ethosu_mailbox_pong(struct ethosu_mailbox *mbox); int ethosu_mailbox_version_request(struct ethosu_mailbox *mbox); /** + * ethosu_mailbox_capabilities_request() - Send capabilities request + * + * Return: 0 on success, else error code. + */ +int ethosu_mailbox_capabilities_request(struct ethosu_mailbox *mbox, + void *user_arg); + +/** * ethosu_mailbox_inference() - Send inference * * Return: 0 on success, else error code. diff --git a/kernel/uapi/ethosu.h b/kernel/uapi/ethosu.h index 1e53c91..3e4e7a3 100644 --- a/kernel/uapi/ethosu.h +++ b/kernel/uapi/ethosu.h @@ -44,6 +44,7 @@ namespace EthosU { #define ETHOSU_IOCTL_PING ETHOSU_IO(0x00) #define ETHOSU_IOCTL_VERSION_REQ ETHOSU_IO(0x01) +#define ETHOSU_IOCTL_CAPABILITIES_REQ ETHOSU_IO(0x02) #define ETHOSU_IOCTL_BUFFER_CREATE ETHOSU_IOR(0x10, \ struct ethosu_uapi_buffer_create) #define ETHOSU_IOCTL_BUFFER_SET ETHOSU_IOR(0x11, \ @@ -125,6 +126,56 @@ struct ethosu_uapi_pmu_counts { }; /** + * struct ethosu_uapi_device_hw_id - Device hardware identification + * @version_status: Version status + * @version_minor: Version minor + * @version_major: Version major + * @product_major: Product major + * @arch_patch_rev: Architecture version patch + * @arch_minor_rev: Architecture version minor + * @arch_major_rev: Architecture version major + */ +struct ethosu_uapi_device_hw_id { + __u32 version_status; + __u32 version_minor; + __u32 version_major; + __u32 product_major; + __u32 arch_patch_rev; + __u32 arch_minor_rev; + __u32 arch_major_rev; +}; + +/** + * struct ethosu_uapi_device_hw_cfg - Device hardware configuration + * @macs_per_cc: MACs per clock cycle + * @cmd_stream_version: NPU command stream version + * @shram_size: SHRAM size + * @custom_dma: Custom DMA enabled + */ +struct ethosu_uapi_device_hw_cfg { + __u32 macs_per_cc; + __u32 cmd_stream_version; + __u32 shram_size; + __u32 custom_dma; +}; + +/** + * struct ethosu_uapi_capabilities - Device capabilities + * @hw_id: Hardware identification + * @hw_cfg: Hardware configuration + * @driver_patch_rev: Driver version patch + * @driver_minor_rev: Driver version minor + * @driver_major_rev: Driver version major + */ +struct ethosu_uapi_device_capabilities { + struct ethosu_uapi_device_hw_id hw_id; + struct ethosu_uapi_device_hw_cfg hw_cfg; + __u32 driver_patch_rev; + __u32 driver_minor_rev; + __u32 driver_major_rev; +}; + +/** * struct ethosu_uapi_inference_create - Create network request * @ifm_count: Number of IFM file descriptors * @ifm_fd: IFM buffer file descriptors |