/* * Copyright 2023 Arm Limited and/or its affiliates * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software * Foundation, and any use by you of this program is subject to the terms * of such GNU licence. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, you can access it online at * http://www.gnu.org/licenses/gpl-2.0.html. * * SPDX-License-Identifier: GPL-2.0-only */ /**************************************************************************** * Includes ****************************************************************************/ #include "ethosu_version.h" #include "ethosu_core_rpmsg.h" #include /**************************************************************************** * Defines ****************************************************************************/ #define VERSION_RESP_TIMEOUT_MS 2000 /**************************************************************************** * Functions ****************************************************************************/ static void ethosu_version_fail(struct ethosu_mailbox_msg *msg) { struct ethosu_version *version = container_of(msg, typeof(*version), msg); if (completion_done(&version->done)) return; version->errno = -EFAULT; complete(&version->done); } void ethosu_version_rsp(struct ethosu_mailbox *mailbox, int msg_id, struct ethosu_core_msg_version_rsp *rsp) { struct device *dev = mailbox->dev; struct ethosu_mailbox_msg *msg; struct ethosu_version *version; msg = ethosu_mailbox_find(mailbox, msg_id, ETHOSU_CORE_MSG_VERSION_REQ); if (IS_ERR(msg)) { dev_warn(dev, "Id for version msg not found. Id=0x%0x: %ld\n", msg_id, PTR_ERR(msg)); return; } version = container_of(msg, typeof(*version), msg); if (completion_done(&version->done)) return; if (rsp->major != ETHOSU_CORE_MSG_VERSION_MAJOR || rsp->minor != ETHOSU_CORE_MSG_VERSION_MINOR) { dev_warn(dev, "Msg: Protocol version mismatch. Expected %u.%u.X but got %u.%u.%u", ETHOSU_CORE_MSG_VERSION_MAJOR, ETHOSU_CORE_MSG_VERSION_MINOR, rsp->major, rsp->minor, rsp->patch); version->errno = -EPROTO; } else { version->errno = 0; } complete(&version->done); } int ethosu_version_check_request(struct device *dev, struct ethosu_mailbox *mailbox) { struct ethosu_version *version; int ret; int timeout; version = devm_kzalloc(dev, sizeof(*version), GFP_KERNEL); if (!version) return -ENOMEM; version->dev = dev; init_completion(&version->done); version->msg.fail = ethosu_version_fail; ret = ethosu_mailbox_register(mailbox, &version->msg); if (ret < 0) goto free_version; dev_dbg(dev, "Protocol version request created. Id=0x%x, handle=%pK\n", version->msg.id, version); ret = ethosu_mailbox_version_request(mailbox, &version->msg); if (ret) goto deregister; /* Unlock the mutex to not block other messages while waiting */ device_unlock(dev); /* Wait for version response */ timeout = wait_for_completion_timeout(&version->done, msecs_to_jiffies( VERSION_RESP_TIMEOUT_MS)); /* Take back the mutex before resuming to do anything */ device_lock(dev); if (0 == timeout) { dev_warn(dev, "Protocol version response timeout"); ret = -ETIME; goto deregister; } if (version->errno) { ret = version->errno; goto deregister; } deregister: ethosu_mailbox_deregister(mailbox, &version->msg); free_version: dev_dbg(dev, "Protocol version destroy. Id=0x%x, handle=%pK\n", version->msg.id, version); devm_kfree(dev, version); return ret; }