blob: d5f77f2f28ae7c471b2ba0abf3065206d436cfb6 [file] [log] [blame]
Davide Grohmann32660f92022-04-27 16:49:07 +02001/*
2 * Copyright (c) 2022 Arm Limited.
3 *
4 * This program is free software and is provided to you under the terms of the
5 * GNU General Public License version 2 as published by the Free Software
6 * Foundation, and any use by you of this program is subject to the terms
7 * of such GNU licence.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, you can access it online at
16 * http://www.gnu.org/licenses/gpl-2.0.html.
17 *
18 * SPDX-License-Identifier: GPL-2.0-only
19 */
20
21/****************************************************************************
22 * Includes
23 ****************************************************************************/
24
25#include "ethosu_capabilities.h"
26
27#include "ethosu_device.h"
28
29#include <linux/delay.h>
30#include <linux/dma-mapping.h>
31#include <linux/errno.h>
32
33/****************************************************************************
34 * Defines
35 ****************************************************************************/
36
37#define CAPABILITIES_RESP_TIMEOUT_MS 2000
38
39/****************************************************************************
40 * Functions
41 ****************************************************************************/
42
43static inline int ethosu_capabilities_send(struct ethosu_capabilities *cap)
44{
45 return ethosu_mailbox_capabilities_request(&cap->edev->mailbox,
46 &cap->msg);
47}
48
49static void ethosu_capabilities_fail(struct ethosu_mailbox_msg *msg)
50{
51 struct ethosu_capabilities *cap =
52 container_of(msg, typeof(*cap), msg);
53
54 if (completion_done(&cap->done))
55 return;
56
57 cap->errno = -EFAULT;
58 complete(&cap->done);
59}
60
61static int ethosu_capabilities_resend(struct ethosu_mailbox_msg *msg)
62{
63 struct ethosu_capabilities *cap =
64 container_of(msg, typeof(*cap), msg);
65
66 /* Don't resend request if response has already been received */
67 if (completion_done(&cap->done))
68 return 0;
69
70 /* Resend request */
71 return ethosu_capabilities_send(cap);
72}
73
74void ethosu_capability_rsp(struct ethosu_device *edev,
75 struct ethosu_core_msg_capabilities_rsp *rsp)
76{
77 int id = (int)rsp->user_arg;
78 struct ethosu_mailbox_msg *msg;
79 struct ethosu_capabilities *cap;
80
81 msg = ethosu_mailbox_find(&edev->mailbox, id);
82 if (IS_ERR(msg)) {
83 dev_warn(edev->dev,
84 "Id for capabilities msg not found. id=%d\n",
85 id);
86
87 return;
88 }
89
90 cap = container_of(msg, typeof(*cap), msg);
91
92 if (completion_done(&cap->done))
93 return;
94
95 cap->uapi->hw_id.version_status = rsp->version_status;
96 cap->uapi->hw_id.version_minor = rsp->version_minor;
97 cap->uapi->hw_id.version_major = rsp->version_major;
98 cap->uapi->hw_id.product_major = rsp->product_major;
99 cap->uapi->hw_id.arch_patch_rev = rsp->arch_patch_rev;
100 cap->uapi->hw_id.arch_minor_rev = rsp->arch_minor_rev;
101 cap->uapi->hw_id.arch_major_rev = rsp->arch_major_rev;
102 cap->uapi->driver_patch_rev = rsp->driver_patch_rev;
103 cap->uapi->driver_minor_rev = rsp->driver_minor_rev;
104 cap->uapi->driver_major_rev = rsp->driver_major_rev;
105 cap->uapi->hw_cfg.macs_per_cc = rsp->macs_per_cc;
106 cap->uapi->hw_cfg.cmd_stream_version = rsp->cmd_stream_version;
107 cap->uapi->hw_cfg.custom_dma = rsp->custom_dma;
108
109 cap->errno = 0;
110 complete(&cap->done);
111}
112
113int ethosu_capabilities_request(struct ethosu_device *edev,
114 struct ethosu_uapi_device_capabilities *uapi)
115{
116 struct ethosu_capabilities *cap;
117 int ret;
118 int timeout;
119
120 cap = devm_kzalloc(edev->dev, sizeof(struct ethosu_capabilities),
121 GFP_KERNEL);
122 if (!cap)
123 return -ENOMEM;
124
125 cap->edev = edev;
126 cap->uapi = uapi;
127 init_completion(&cap->done);
128 cap->msg.fail = ethosu_capabilities_fail;
129 cap->msg.resend = ethosu_capabilities_resend;
130
131 ret = ethosu_mailbox_register(&cap->edev->mailbox, &cap->msg);
132 if (ret < 0)
133 goto kfree;
134
135 dev_info(edev->dev, "Capabilities create. Id=%d, handle=0x%p\n",
136 cap->msg.id, cap);
137
138 ret = ethosu_capabilities_send(cap);
139 if (0 != ret)
140 goto deregister;
141
142 /* Unlock the mutex before going to block on the condition */
143 mutex_unlock(&edev->mutex);
144
145 /* wait for response to arrive back */
146 timeout = wait_for_completion_timeout(&cap->done,
147 msecs_to_jiffies(
148 CAPABILITIES_RESP_TIMEOUT_MS));
149
150 /* take back the mutex before resuming to do anything */
151 mutex_lock(&edev->mutex);
152
153 if (0 == timeout) {
154 dev_warn(edev->dev, "Capabilities response timeout");
155 ret = -ETIME;
156 goto deregister;
157 }
158
159 if (cap->errno) {
160 ret = cap->errno;
161 goto deregister;
162 }
163
164deregister:
165 ethosu_mailbox_deregister(&cap->edev->mailbox, &cap->msg);
166
167kfree:
168 dev_info(cap->edev->dev, "Capabilities destroy. Id=%d, handle=0x%p\n",
169 cap->msg.id, cap);
170 devm_kfree(cap->edev->dev, cap);
171
172 return ret;
173}