aboutsummaryrefslogtreecommitdiff
path: root/kernel/ethosu_device.c
diff options
context:
space:
mode:
authorDavide Grohmann <davide.grohmann@arm.com>2022-04-27 16:49:07 +0200
committerDavide Grohmann <davide.grohmann@arm.com>2022-05-23 15:42:30 +0200
commit32660f9ff9608dc595f4bdf3944a3ceb37d67a79 (patch)
treec57eaef314cc0600c2df6de9426c15709f42bccf /kernel/ethosu_device.c
parentb9248a425e7f72d240d11852c72c44bae4d38bac (diff)
downloadethos-u-linux-driver-stack-32660f9ff9608dc595f4bdf3944a3ceb37d67a79.tar.gz
Use ids for identifying messages sent to EthosU firmware
Avoid to use pointers to kernel memory as identify messages, prior this change, if memory is reused that can lead to unexpected conflicts. Remove ref counting from capabilities and network_info since memory is freed in only one place. Finally, extract the capabilities code in its own files. Change-Id: I9ab7257f3ab85fa3347be65b3739e0daf9b5a441
Diffstat (limited to 'kernel/ethosu_device.c')
-rw-r--r--kernel/ethosu_device.c160
1 files changed, 9 insertions, 151 deletions
diff --git a/kernel/ethosu_device.c b/kernel/ethosu_device.c
index 6b911ca..6bc3c28 100644
--- a/kernel/ethosu_device.c
+++ b/kernel/ethosu_device.c
@@ -26,13 +26,13 @@
#include "ethosu_buffer.h"
#include "ethosu_core_interface.h"
+#include "ethosu_capabilities.h"
#include "ethosu_inference.h"
#include "ethosu_cancel_inference.h"
#include "ethosu_network.h"
#include "ethosu_network_info.h"
#include "uapi/ethosu.h"
-#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/errno.h>
#include <linux/fs.h>
@@ -49,158 +49,10 @@
#define DMA_ADDR_BITS 32 /* Number of address bits */
-#define CAPABILITIES_RESP_TIMEOUT_MS 2000
-
/****************************************************************************
* Functions
****************************************************************************/
-static void ethosu_capabilities_destroy(struct kref *kref)
-{
- struct ethosu_capabilities *cap =
- container_of(kref, struct ethosu_capabilities, refcount);
-
- dev_info(cap->edev->dev, "Capabilities destroy. handle=0x%pK\n", cap);
-
- list_del(&cap->msg.list);
-
- devm_kfree(cap->edev->dev, cap);
-}
-
-static int ethosu_capabilities_send(struct ethosu_capabilities *cap)
-{
- int ret;
-
- ret = ethosu_mailbox_capabilities_request(&cap->edev->mailbox, cap);
- if (ret)
- return ret;
-
- return 0;
-}
-
-static void ethosu_capabilities_fail(struct ethosu_mailbox_msg *msg)
-{
- struct ethosu_capabilities *cap =
- container_of(msg, typeof(*cap), msg);
-
- if (completion_done(&cap->done))
- return;
-
- cap->errno = -EFAULT;
- complete(&cap->done);
-}
-
-static int ethosu_capabilities_resend(struct ethosu_mailbox_msg *msg)
-{
- struct ethosu_capabilities *cap =
- container_of(msg, typeof(*cap), msg);
- int ret;
-
- /* Don't resend request if response has already been received */
- if (completion_done(&cap->done))
- return 0;
-
- /* Resend request */
- ret = ethosu_capabilities_send(cap);
- if (ret)
- return ret;
-
- return 0;
-}
-
-static void ethosu_capability_rsp(struct ethosu_device *edev,
- struct ethosu_core_msg_capabilities_rsp *msg)
-{
- struct ethosu_capabilities *cap =
- (struct ethosu_capabilities *)msg->user_arg;
- struct ethosu_uapi_device_capabilities *capabilities;
- int ret;
-
- ret = ethosu_mailbox_find(&edev->mailbox, &cap->msg);
- if (ret) {
- dev_warn(edev->dev,
- "Capabilities not found in pending list. handle=0x%p\n",
- cap);
-
- return;
- }
-
- if (completion_done(&cap->done))
- return;
-
- 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.custom_dma = msg->custom_dma;
-
- cap->errno = 0;
- complete(&cap->done);
-}
-
-static int ethosu_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->msg.list, &edev->mailbox.pending_list);
- cap->msg.fail = ethosu_capabilities_fail;
- cap->msg.resend = ethosu_capabilities_resend;
-
- ret = ethosu_capabilities_send(cap);
- if (0 != ret)
- goto put_kref;
-
- /* 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 */
- mutex_lock(&edev->mutex);
-
- if (0 == timeout) {
- dev_warn(edev->dev, "Capabilities response timeout");
- ret = -EIO;
- goto put_kref;
- }
-
- if (cap->errno)
- goto put_kref;
-
- ret = copy_to_user(udata, &uapi, sizeof(uapi)) ? -EFAULT : 0;
-
-put_kref:
- kref_put(&cap->refcount, ethosu_capabilities_destroy);
-
- return ret;
-}
-
/* Incoming messages */
static int ethosu_handle_msg(struct ethosu_device *edev)
{
@@ -463,10 +315,16 @@ 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:
+ case ETHOSU_IOCTL_CAPABILITIES_REQ: {
+ struct ethosu_uapi_device_capabilities uapi;
dev_info(edev->dev, "Ioctl: Send capabilities request\n");
- ret = ethosu_capabilities_request(edev, udata);
+ ret = ethosu_capabilities_request(edev, &uapi);
+ if (ret)
+ break;
+
+ ret = copy_to_user(udata, &uapi, sizeof(uapi)) ? -EFAULT : 0;
break;
+ }
case ETHOSU_IOCTL_PING: {
dev_info(edev->dev, "Ioctl: Send ping\n");
ret = ethosu_mailbox_ping(&edev->mailbox);