From 7c24c770be3b3e25822cf7c45619ee20ed61c172 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonny=20Sv=C3=A4rd?= Date: Thu, 14 Jan 2021 19:53:17 +0100 Subject: Improve mailbox message handling Introduce a 32b magic for each message. Verify the magic for all incoming messages. Add reset function - in case of protocol error, effectively reset/empty the incoming queue. Add an error message type and message Add version request/response Verify payload length of responses (when applicable) Change-Id: I8aadd4012024492533d52e2cdb38630fce5c36e2 --- kernel/ethosu_device.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 64 insertions(+), 5 deletions(-) (limited to 'kernel/ethosu_device.c') diff --git a/kernel/ethosu_device.c b/kernel/ethosu_device.c index 5301f86..e82b4c0 100644 --- a/kernel/ethosu_device.c +++ b/kernel/ethosu_device.c @@ -55,14 +55,17 @@ * Functions ****************************************************************************/ +/* Incoming messages */ static int ethosu_handle_msg(struct ethosu_device *edev) { + 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; } data; - int ret; /* Read message */ ret = ethosu_mailbox_read(&edev->mailbox, &header, &data, sizeof(data)); @@ -70,24 +73,71 @@ static int ethosu_handle_msg(struct ethosu_device *edev) return ret; switch (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)); + 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); + ret = -EBADMSG; + break; case ETHOSU_CORE_MSG_PING: dev_info(edev->dev, "Msg: Ping\n"); - ret = ethosu_mailbox_ping(&edev->mailbox); + ret = ethosu_mailbox_pong(&edev->mailbox); break; case ETHOSU_CORE_MSG_PONG: dev_info(edev->dev, "Msg: Pong\n"); 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)); + 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); ethosu_inference_rsp(edev, &data.inf); 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)); + ret = -EBADMSG; + break; + } + + dev_info(edev->dev, "Msg: Version response v%u.%u.%u\n", + data.version.major, data.version.minor, + data.version.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", + ETHOSU_CORE_MSG_VERSION_MAJOR, + ETHOSU_CORE_MSG_VERSION_MINOR, + ETHOSU_CORE_MSG_VERSION_PATCH); + } + + break; + default: - dev_warn(edev->dev, - "Msg: Unsupported msg type. type=%u, length=%u", - header.type, header.length); + /* This should not happen due to version checks */ + dev_warn(edev->dev, "Msg: Protocol error\n"); + ret = -EPROTO; break; } @@ -122,6 +172,10 @@ static long ethosu_ioctl(struct file *file, dev_info(edev->dev, "Ioctl. cmd=%u, arg=%lu\n", cmd, arg); switch (cmd) { + case ETHOSU_IOCTL_VERSION_REQ: + dev_info(edev->dev, "Ioctl: Send version request\n"); + ret = ethosu_mailbox_version_request(&edev->mailbox); + break; case ETHOSU_IOCTL_PING: { dev_info(edev->dev, "Ioctl: Send ping\n"); ret = ethosu_mailbox_ping(&edev->mailbox); @@ -173,6 +227,11 @@ static void ethosu_mbox_rx(void *user_arg) 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); mutex_unlock(&edev->mutex); -- cgit v1.2.1