diff options
-rw-r--r-- | Documentation/remoteproc.txt | 324 | ||||
-rw-r--r-- | MAINTAINERS | 7 | ||||
-rw-r--r-- | drivers/Kconfig | 2 | ||||
-rw-r--r-- | drivers/Makefile | 1 | ||||
-rw-r--r-- | drivers/remoteproc/Kconfig | 3 | ||||
-rw-r--r-- | drivers/remoteproc/Makefile | 6 | ||||
-rw-r--r-- | drivers/remoteproc/remoteproc_core.c | 1410 | ||||
-rw-r--r-- | drivers/remoteproc/remoteproc_internal.h | 44 | ||||
-rw-r--r-- | include/linux/remoteproc.h | 265 |
9 files changed, 2062 insertions, 0 deletions
diff --git a/Documentation/remoteproc.txt b/Documentation/remoteproc.txt new file mode 100644 index 000000000000..23ff7349ffe7 --- /dev/null +++ b/Documentation/remoteproc.txt | |||
@@ -0,0 +1,324 @@ | |||
1 | Remote Processor Framework | ||
2 | |||
3 | 1. Introduction | ||
4 | |||
5 | Modern SoCs typically have heterogeneous remote processor devices in asymmetric | ||
6 | multiprocessing (AMP) configurations, which may be running different instances | ||
7 | of operating system, whether it's Linux or any other flavor of real-time OS. | ||
8 | |||
9 | OMAP4, for example, has dual Cortex-A9, dual Cortex-M3 and a C64x+ DSP. | ||
10 | In a typical configuration, the dual cortex-A9 is running Linux in a SMP | ||
11 | configuration, and each of the other three cores (two M3 cores and a DSP) | ||
12 | is running its own instance of RTOS in an AMP configuration. | ||
13 | |||
14 | The remoteproc framework allows different platforms/architectures to | ||
15 | control (power on, load firmware, power off) those remote processors while | ||
16 | abstracting the hardware differences, so the entire driver doesn't need to be | ||
17 | duplicated. In addition, this framework also adds rpmsg virtio devices | ||
18 | for remote processors that supports this kind of communication. This way, | ||
19 | platform-specific remoteproc drivers only need to provide a few low-level | ||
20 | handlers, and then all rpmsg drivers will then just work | ||
21 | (for more information about the virtio-based rpmsg bus and its drivers, | ||
22 | please read Documentation/rpmsg.txt). | ||
23 | |||
24 | 2. User API | ||
25 | |||
26 | int rproc_boot(struct rproc *rproc) | ||
27 | - Boot a remote processor (i.e. load its firmware, power it on, ...). | ||
28 | If the remote processor is already powered on, this function immediately | ||
29 | returns (successfully). | ||
30 | Returns 0 on success, and an appropriate error value otherwise. | ||
31 | Note: to use this function you should already have a valid rproc | ||
32 | handle. There are several ways to achieve that cleanly (devres, pdata, | ||
33 | the way remoteproc_rpmsg.c does this, or, if this becomes prevalent, we | ||
34 | might also consider using dev_archdata for this). See also | ||
35 | rproc_get_by_name() below. | ||
36 | |||
37 | void rproc_shutdown(struct rproc *rproc) | ||
38 | - Power off a remote processor (previously booted with rproc_boot()). | ||
39 | In case @rproc is still being used by an additional user(s), then | ||
40 | this function will just decrement the power refcount and exit, | ||
41 | without really powering off the device. | ||
42 | Every call to rproc_boot() must (eventually) be accompanied by a call | ||
43 | to rproc_shutdown(). Calling rproc_shutdown() redundantly is a bug. | ||
44 | Notes: | ||
45 | - we're not decrementing the rproc's refcount, only the power refcount. | ||
46 | which means that the @rproc handle stays valid even after | ||
47 | rproc_shutdown() returns, and users can still use it with a subsequent | ||
48 | rproc_boot(), if needed. | ||
49 | - don't call rproc_shutdown() to unroll rproc_get_by_name(), exactly | ||
50 | because rproc_shutdown() _does not_ decrement the refcount of @rproc. | ||
51 | To decrement the refcount of @rproc, use rproc_put() (but _only_ if | ||
52 | you acquired @rproc using rproc_get_by_name()). | ||
53 | |||
54 | struct rproc *rproc_get_by_name(const char *name) | ||
55 | - Find an rproc handle using the remote processor's name, and then | ||
56 | boot it. If it's already powered on, then just immediately return | ||
57 | (successfully). Returns the rproc handle on success, and NULL on failure. | ||
58 | This function increments the remote processor's refcount, so always | ||
59 | use rproc_put() to decrement it back once rproc isn't needed anymore. | ||
60 | Note: currently rproc_get_by_name() and rproc_put() are not used anymore | ||
61 | by the rpmsg bus and its drivers. We need to scrutinize the use cases | ||
62 | that still need them, and see if we can migrate them to use the non | ||
63 | name-based boot/shutdown interface. | ||
64 | |||
65 | void rproc_put(struct rproc *rproc) | ||
66 | - Decrement @rproc's power refcount and shut it down if it reaches zero | ||
67 | (essentially by just calling rproc_shutdown), and then decrement @rproc's | ||
68 | validity refcount too. | ||
69 | After this function returns, @rproc may _not_ be used anymore, and its | ||
70 | handle should be considered invalid. | ||
71 | This function should be called _iff_ the @rproc handle was grabbed by | ||
72 | calling rproc_get_by_name(). | ||
73 | |||
74 | 3. Typical usage | ||
75 | |||
76 | #include <linux/remoteproc.h> | ||
77 | |||
78 | /* in case we were given a valid 'rproc' handle */ | ||
79 | int dummy_rproc_example(struct rproc *my_rproc) | ||
80 | { | ||
81 | int ret; | ||
82 | |||
83 | /* let's power on and boot our remote processor */ | ||
84 | ret = rproc_boot(my_rproc); | ||
85 | if (ret) { | ||
86 | /* | ||
87 | * something went wrong. handle it and leave. | ||
88 | */ | ||
89 | } | ||
90 | |||
91 | /* | ||
92 | * our remote processor is now powered on... give it some work | ||
93 | */ | ||
94 | |||
95 | /* let's shut it down now */ | ||
96 | rproc_shutdown(my_rproc); | ||
97 | } | ||
98 | |||
99 | 4. API for implementors | ||
100 | |||
101 | struct rproc *rproc_alloc(struct device *dev, const char *name, | ||
102 | const struct rproc_ops *ops, | ||
103 | const char *firmware, int len) | ||
104 | - Allocate a new remote processor handle, but don't register | ||
105 | it yet. Required parameters are the underlying device, the | ||
106 | name of this remote processor, platform-specific ops handlers, | ||
107 | the name of the firmware to boot this rproc with, and the | ||
108 | length of private data needed by the allocating rproc driver (in bytes). | ||
109 | |||
110 | This function should be used by rproc implementations during | ||
111 | initialization of the remote processor. | ||
112 | After creating an rproc handle using this function, and when ready, | ||
113 | implementations should then call rproc_register() to complete | ||
114 | the registration of the remote processor. | ||
115 | On success, the new rproc is returned, and on failure, NULL. | ||
116 | |||
117 | Note: _never_ directly deallocate @rproc, even if it was not registered | ||
118 | yet. Instead, if you just need to unroll rproc_alloc(), use rproc_free(). | ||
119 | |||
120 | void rproc_free(struct rproc *rproc) | ||
121 | - Free an rproc handle that was allocated by rproc_alloc. | ||
122 | This function should _only_ be used if @rproc was only allocated, | ||
123 | but not registered yet. | ||
124 | If @rproc was already successfully registered (by calling | ||
125 | rproc_register()), then use rproc_unregister() instead. | ||
126 | |||
127 | int rproc_register(struct rproc *rproc) | ||
128 | - Register @rproc with the remoteproc framework, after it has been | ||
129 | allocated with rproc_alloc(). | ||
130 | This is called by the platform-specific rproc implementation, whenever | ||
131 | a new remote processor device is probed. | ||
132 | Returns 0 on success and an appropriate error code otherwise. | ||
133 | Note: this function initiates an asynchronous firmware loading | ||
134 | context, which will look for virtio devices supported by the rproc's | ||
135 | firmware. | ||
136 | If found, those virtio devices will be created and added, so as a result | ||
137 | of registering this remote processor, additional virtio drivers might get | ||
138 | probed. | ||
139 | Currently, though, we only support a single RPMSG virtio vdev per remote | ||
140 | processor. | ||
141 | |||
142 | int rproc_unregister(struct rproc *rproc) | ||
143 | - Unregister a remote processor, and decrement its refcount. | ||
144 | If its refcount drops to zero, then @rproc will be freed. If not, | ||
145 | it will be freed later once the last reference is dropped. | ||
146 | |||
147 | This function should be called when the platform specific rproc | ||
148 | implementation decides to remove the rproc device. it should | ||
149 | _only_ be called if a previous invocation of rproc_register() | ||
150 | has completed successfully. | ||
151 | |||
152 | After rproc_unregister() returns, @rproc is _not_ valid anymore and | ||
153 | it shouldn't be used. More specifically, don't call rproc_free() | ||
154 | or try to directly free @rproc after rproc_unregister() returns; | ||
155 | none of these are needed, and calling them is a bug. | ||
156 | |||
157 | Returns 0 on success and -EINVAL if @rproc isn't valid. | ||
158 | |||
159 | 5. Implementation callbacks | ||
160 | |||
161 | These callbacks should be provided by platform-specific remoteproc | ||
162 | drivers: | ||
163 | |||
164 | /** | ||
165 | * struct rproc_ops - platform-specific device handlers | ||
166 | * @start: power on the device and boot it | ||
167 | * @stop: power off the device | ||
168 | * @kick: kick a virtqueue (virtqueue id given as a parameter) | ||
169 | */ | ||
170 | struct rproc_ops { | ||
171 | int (*start)(struct rproc *rproc); | ||
172 | int (*stop)(struct rproc *rproc); | ||
173 | void (*kick)(struct rproc *rproc, int vqid); | ||
174 | }; | ||
175 | |||
176 | Every remoteproc implementation should at least provide the ->start and ->stop | ||
177 | handlers. If rpmsg functionality is also desired, then the ->kick handler | ||
178 | should be provided as well. | ||
179 | |||
180 | The ->start() handler takes an rproc handle and should then power on the | ||
181 | device and boot it (use rproc->priv to access platform-specific private data). | ||
182 | The boot address, in case needed, can be found in rproc->bootaddr (remoteproc | ||
183 | core puts there the ELF entry point). | ||
184 | On success, 0 should be returned, and on failure, an appropriate error code. | ||
185 | |||
186 | The ->stop() handler takes an rproc handle and powers the device down. | ||
187 | On success, 0 is returned, and on failure, an appropriate error code. | ||
188 | |||
189 | The ->kick() handler takes an rproc handle, and an index of a virtqueue | ||
190 | where new message was placed in. Implementations should interrupt the remote | ||
191 | processor and let it know it has pending messages. Notifying remote processors | ||
192 | the exact virtqueue index to look in is optional: it is easy (and not | ||
193 | too expensive) to go through the existing virtqueues and look for new buffers | ||
194 | in the used rings. | ||
195 | |||
196 | 6. Binary Firmware Structure | ||
197 | |||
198 | At this point remoteproc only supports ELF32 firmware binaries. However, | ||
199 | it is quite expected that other platforms/devices which we'd want to | ||
200 | support with this framework will be based on different binary formats. | ||
201 | |||
202 | When those use cases show up, we will have to decouple the binary format | ||
203 | from the framework core, so we can support several binary formats without | ||
204 | duplicating common code. | ||
205 | |||
206 | When the firmware is parsed, its various segments are loaded to memory | ||
207 | according to the specified device address (might be a physical address | ||
208 | if the remote processor is accessing memory directly). | ||
209 | |||
210 | In addition to the standard ELF segments, most remote processors would | ||
211 | also include a special section which we call "the resource table". | ||
212 | |||
213 | The resource table contains system resources that the remote processor | ||
214 | requires before it should be powered on, such as allocation of physically | ||
215 | contiguous memory, or iommu mapping of certain on-chip peripherals. | ||
216 | Remotecore will only power up the device after all the resource table's | ||
217 | requirement are met. | ||
218 | |||
219 | In addition to system resources, the resource table may also contain | ||
220 | resource entries that publish the existence of supported features | ||
221 | or configurations by the remote processor, such as trace buffers and | ||
222 | supported virtio devices (and their configurations). | ||
223 | |||
224 | Currently the resource table is just an array of: | ||
225 | |||
226 | /** | ||
227 | * struct fw_resource - describes an entry from the resource section | ||
228 | * @type: resource type | ||
229 | * @id: index number of the resource | ||
230 | * @da: device address of the resource | ||
231 | * @pa: physical address of the resource | ||
232 | * @len: size, in bytes, of the resource | ||
233 | * @flags: properties of the resource, e.g. iommu protection required | ||
234 | * @reserved: must be 0 atm | ||
235 | * @name: name of resource | ||
236 | */ | ||
237 | struct fw_resource { | ||
238 | u32 type; | ||
239 | u32 id; | ||
240 | u64 da; | ||
241 | u64 pa; | ||
242 | u32 len; | ||
243 | u32 flags; | ||
244 | u8 reserved[16]; | ||
245 | u8 name[48]; | ||
246 | } __packed; | ||
247 | |||
248 | Some resources entries are mere announcements, where the host is informed | ||
249 | of specific remoteproc configuration. Other entries require the host to | ||
250 | do something (e.g. reserve a requested resource) and possibly also reply | ||
251 | by overwriting a member inside 'struct fw_resource' with info about the | ||
252 | allocated resource. | ||
253 | |||
254 | Different resource entries use different members of this struct, | ||
255 | with different meanings. This is pretty limiting and error-prone, | ||
256 | so the plan is to move to variable-length TLV-based resource entries, | ||
257 | where each resource will begin with a type and length fields, followed by | ||
258 | its own specific structure. | ||
259 | |||
260 | Here are the resource types that are currently being used: | ||
261 | |||
262 | /** | ||
263 | * enum fw_resource_type - types of resource entries | ||
264 | * | ||
265 | * @RSC_CARVEOUT: request for allocation of a physically contiguous | ||
266 | * memory region. | ||
267 | * @RSC_DEVMEM: request to iommu_map a memory-based peripheral. | ||
268 | * @RSC_TRACE: announces the availability of a trace buffer into which | ||
269 | * the remote processor will be writing logs. In this case, | ||
270 | * 'da' indicates the device address where logs are written to, | ||
271 | * and 'len' is the size of the trace buffer. | ||
272 | * @RSC_VRING: request for allocation of a virtio vring (address should | ||
273 | * be indicated in 'da', and 'len' should contain the number | ||
274 | * of buffers supported by the vring). | ||
275 | * @RSC_VIRTIO_DEV: announces support for a virtio device, and serves as | ||
276 | * the virtio header. 'da' contains the virtio device | ||
277 | * features, 'pa' holds the virtio guest features (host | ||
278 | * will write them here after they're negotiated), 'len' | ||
279 | * holds the virtio status, and 'flags' holds the virtio | ||
280 | * device id (currently only VIRTIO_ID_RPMSG is supported). | ||
281 | */ | ||
282 | enum fw_resource_type { | ||
283 | RSC_CARVEOUT = 0, | ||
284 | RSC_DEVMEM = 1, | ||
285 | RSC_TRACE = 2, | ||
286 | RSC_VRING = 3, | ||
287 | RSC_VIRTIO_DEV = 4, | ||
288 | RSC_VIRTIO_CFG = 5, | ||
289 | }; | ||
290 | |||
291 | Most of the resource entries share the basic idea of address/length | ||
292 | negotiation with the host: the firmware usually asks for memory | ||
293 | of size 'len' bytes, and the host needs to allocate it and provide | ||
294 | the device/physical address (when relevant) in 'da'/'pa' respectively. | ||
295 | |||
296 | If the firmware is compiled with hard coded device addresses, and | ||
297 | can't handle dynamically allocated 'da' values, then the 'da' field | ||
298 | will contain the expected device addresses (today we actually only support | ||
299 | this scheme, as there aren't yet any use cases for dynamically allocated | ||
300 | device addresses). | ||
301 | |||
302 | We also expect that platform-specific resource entries will show up | ||
303 | at some point. When that happens, we could easily add a new RSC_PLAFORM | ||
304 | type, and hand those resources to the platform-specific rproc driver to handle. | ||
305 | |||
306 | 7. Virtio and remoteproc | ||
307 | |||
308 | The firmware should provide remoteproc information about virtio devices | ||
309 | that it supports, and their configurations: a RSC_VIRTIO_DEV resource entry | ||
310 | should specify the virtio device id, and subsequent RSC_VRING resource entries | ||
311 | should indicate the vring size (i.e. how many buffers do they support) and | ||
312 | where should they be mapped (i.e. which device address). Note: the alignment | ||
313 | between the consumer and producer parts of the vring is assumed to be 4096. | ||
314 | |||
315 | At this point we only support a single virtio rpmsg device per remote | ||
316 | processor, but the plan is to remove this limitation. In addition, once we | ||
317 | move to TLV-based resource table, the plan is to have a single RSC_VIRTIO | ||
318 | entry per supported virtio device, which will include the virtio header, | ||
319 | the vrings information and the virtio config space. | ||
320 | |||
321 | Of course, RSC_VIRTIO resource entries are only good enough for static | ||
322 | allocation of virtio devices. Dynamic allocations will also be made possible | ||
323 | using the rpmsg bus (similar to how we already do dynamic allocations of | ||
324 | rpmsg channels; read more about it in rpmsg.txt). | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 89b70df91f4f..b611319dc77a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -5548,6 +5548,13 @@ S: Supported | |||
5548 | F: drivers/base/regmap/ | 5548 | F: drivers/base/regmap/ |
5549 | F: include/linux/regmap.h | 5549 | F: include/linux/regmap.h |
5550 | 5550 | ||
5551 | REMOTE PROCESSOR (REMOTEPROC) SUBSYSTEM | ||
5552 | M: Ohad Ben-Cohen <ohad@wizery.com> | ||
5553 | S: Maintained | ||
5554 | F: drivers/remoteproc/ | ||
5555 | F: Documentation/remoteproc.txt | ||
5556 | F: include/linux/remoteproc.txt | ||
5557 | |||
5551 | RFKILL | 5558 | RFKILL |
5552 | M: Johannes Berg <johannes@sipsolutions.net> | 5559 | M: Johannes Berg <johannes@sipsolutions.net> |
5553 | L: linux-wireless@vger.kernel.org | 5560 | L: linux-wireless@vger.kernel.org |
diff --git a/drivers/Kconfig b/drivers/Kconfig index 5afe5d1f199b..27b34bf41d4c 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig | |||
@@ -132,6 +132,8 @@ source "drivers/clocksource/Kconfig" | |||
132 | 132 | ||
133 | source "drivers/iommu/Kconfig" | 133 | source "drivers/iommu/Kconfig" |
134 | 134 | ||
135 | source "drivers/remoteproc/Kconfig" | ||
136 | |||
135 | source "drivers/virt/Kconfig" | 137 | source "drivers/virt/Kconfig" |
136 | 138 | ||
137 | source "drivers/devfreq/Kconfig" | 139 | source "drivers/devfreq/Kconfig" |
diff --git a/drivers/Makefile b/drivers/Makefile index c07be024b962..f1019b714f27 100644 --- a/drivers/Makefile +++ b/drivers/Makefile | |||
@@ -126,6 +126,7 @@ obj-y += clk/ | |||
126 | obj-$(CONFIG_HWSPINLOCK) += hwspinlock/ | 126 | obj-$(CONFIG_HWSPINLOCK) += hwspinlock/ |
127 | obj-$(CONFIG_NFC) += nfc/ | 127 | obj-$(CONFIG_NFC) += nfc/ |
128 | obj-$(CONFIG_IOMMU_SUPPORT) += iommu/ | 128 | obj-$(CONFIG_IOMMU_SUPPORT) += iommu/ |
129 | obj-$(CONFIG_REMOTEPROC) += remoteproc/ | ||
129 | 130 | ||
130 | # Virtualization drivers | 131 | # Virtualization drivers |
131 | obj-$(CONFIG_VIRT_DRIVERS) += virt/ | 132 | obj-$(CONFIG_VIRT_DRIVERS) += virt/ |
diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig new file mode 100644 index 000000000000..b250b15c0686 --- /dev/null +++ b/drivers/remoteproc/Kconfig | |||
@@ -0,0 +1,3 @@ | |||
1 | # REMOTEPROC gets selected by whoever wants it | ||
2 | config REMOTEPROC | ||
3 | tristate | ||
diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile new file mode 100644 index 000000000000..2a5fd7992f5a --- /dev/null +++ b/drivers/remoteproc/Makefile | |||
@@ -0,0 +1,6 @@ | |||
1 | # | ||
2 | # Generic framework for controlling remote processors | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_REMOTEPROC) += remoteproc.o | ||
6 | remoteproc-y := remoteproc_core.o | ||
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c new file mode 100644 index 000000000000..ad93d7d4ecbb --- /dev/null +++ b/drivers/remoteproc/remoteproc_core.c | |||
@@ -0,0 +1,1410 @@ | |||
1 | /* | ||
2 | * Remote Processor Framework | ||
3 | * | ||
4 | * Copyright (C) 2011 Texas Instruments, Inc. | ||
5 | * Copyright (C) 2011 Google, Inc. | ||
6 | * | ||
7 | * Ohad Ben-Cohen <ohad@wizery.com> | ||
8 | * Brian Swetland <swetland@google.com> | ||
9 | * Mark Grosen <mgrosen@ti.com> | ||
10 | * Fernando Guzman Lugo <fernando.lugo@ti.com> | ||
11 | * Suman Anna <s-anna@ti.com> | ||
12 | * Robert Tivy <rtivy@ti.com> | ||
13 | * Armando Uribe De Leon <x0095078@ti.com> | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or | ||
16 | * modify it under the terms of the GNU General Public License | ||
17 | * version 2 as published by the Free Software Foundation. | ||
18 | * | ||
19 | * This program is distributed in the hope that it will be useful, | ||
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
22 | * GNU General Public License for more details. | ||
23 | */ | ||
24 | |||
25 | #define pr_fmt(fmt) "%s: " fmt, __func__ | ||
26 | |||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/device.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/mutex.h> | ||
32 | #include <linux/dma-mapping.h> | ||
33 | #include <linux/firmware.h> | ||
34 | #include <linux/string.h> | ||
35 | #include <linux/debugfs.h> | ||
36 | #include <linux/remoteproc.h> | ||
37 | #include <linux/iommu.h> | ||
38 | #include <linux/klist.h> | ||
39 | #include <linux/elf.h> | ||
40 | #include <linux/virtio_ids.h> | ||
41 | #include <linux/virtio_ring.h> | ||
42 | |||
43 | #include "remoteproc_internal.h" | ||
44 | |||
45 | static void klist_rproc_get(struct klist_node *n); | ||
46 | static void klist_rproc_put(struct klist_node *n); | ||
47 | |||
48 | /* | ||
49 | * klist of the available remote processors. | ||
50 | * | ||
51 | * We need this in order to support name-based lookups (needed by the | ||
52 | * rproc_get_by_name()). | ||
53 | * | ||
54 | * That said, we don't use rproc_get_by_name() anymore within the rpmsg | ||
55 | * framework. The use cases that do require its existence should be | ||
56 | * scrutinized, and hopefully migrated to rproc_boot() using device-based | ||
57 | * binding. | ||
58 | * | ||
59 | * If/when this materializes, we could drop the klist (and the by_name | ||
60 | * API). | ||
61 | */ | ||
62 | static DEFINE_KLIST(rprocs, klist_rproc_get, klist_rproc_put); | ||
63 | |||
64 | typedef int (*rproc_handle_resources_t)(struct rproc *rproc, | ||
65 | struct fw_resource *rsc, int len); | ||
66 | |||
67 | /* | ||
68 | * This is the IOMMU fault handler we register with the IOMMU API | ||
69 | * (when relevant; not all remote processors access memory through | ||
70 | * an IOMMU). | ||
71 | * | ||
72 | * IOMMU core will invoke this handler whenever the remote processor | ||
73 | * will try to access an unmapped device address. | ||
74 | * | ||
75 | * Currently this is mostly a stub, but it will be later used to trigger | ||
76 | * the recovery of the remote processor. | ||
77 | */ | ||
78 | static int rproc_iommu_fault(struct iommu_domain *domain, struct device *dev, | ||
79 | unsigned long iova, int flags) | ||
80 | { | ||
81 | dev_err(dev, "iommu fault: da 0x%lx flags 0x%x\n", iova, flags); | ||
82 | |||
83 | /* | ||
84 | * Let the iommu core know we're not really handling this fault; | ||
85 | * we just plan to use this as a recovery trigger. | ||
86 | */ | ||
87 | return -ENOSYS; | ||
88 | } | ||
89 | |||
90 | static int rproc_enable_iommu(struct rproc *rproc) | ||
91 | { | ||
92 | struct iommu_domain *domain; | ||
93 | struct device *dev = rproc->dev; | ||
94 | int ret; | ||
95 | |||
96 | /* | ||
97 | * We currently use iommu_present() to decide if an IOMMU | ||
98 | * setup is needed. | ||
99 | * | ||
100 | * This works for simple cases, but will easily fail with | ||
101 | * platforms that do have an IOMMU, but not for this specific | ||
102 | * rproc. | ||
103 | * | ||
104 | * This will be easily solved by introducing hw capabilities | ||
105 | * that will be set by the remoteproc driver. | ||
106 | */ | ||
107 | if (!iommu_present(dev->bus)) { | ||
108 | dev_err(dev, "iommu not found\n"); | ||
109 | return -ENODEV; | ||
110 | } | ||
111 | |||
112 | domain = iommu_domain_alloc(dev->bus); | ||
113 | if (!domain) { | ||
114 | dev_err(dev, "can't alloc iommu domain\n"); | ||
115 | return -ENOMEM; | ||
116 | } | ||
117 | |||
118 | iommu_set_fault_handler(domain, rproc_iommu_fault); | ||
119 | |||
120 | ret = iommu_attach_device(domain, dev); | ||
121 | if (ret) { | ||
122 | dev_err(dev, "can't attach iommu device: %d\n", ret); | ||
123 | goto free_domain; | ||
124 | } | ||
125 | |||
126 | rproc->domain = domain; | ||
127 | |||
128 | return 0; | ||
129 | |||
130 | free_domain: | ||
131 | iommu_domain_free(domain); | ||
132 | return ret; | ||
133 | } | ||
134 | |||
135 | static void rproc_disable_iommu(struct rproc *rproc) | ||
136 | { | ||
137 | struct iommu_domain *domain = rproc->domain; | ||
138 | struct device *dev = rproc->dev; | ||
139 | |||
140 | if (!domain) | ||
141 | return; | ||
142 | |||
143 | iommu_detach_device(domain, dev); | ||
144 | iommu_domain_free(domain); | ||
145 | |||
146 | return; | ||
147 | } | ||
148 | |||
149 | /* | ||
150 | * Some remote processors will ask us to allocate them physically contiguous | ||
151 | * memory regions (which we call "carveouts"), and map them to specific | ||
152 | * device addresses (which are hardcoded in the firmware). | ||
153 | * | ||
154 | * They may then ask us to copy objects into specific device addresses (e.g. | ||
155 | * code/data sections) or expose us certain symbols in other device address | ||
156 | * (e.g. their trace buffer). | ||
157 | * | ||
158 | * This function is an internal helper with which we can go over the allocated | ||
159 | * carveouts and translate specific device address to kernel virtual addresses | ||
160 | * so we can access the referenced memory. | ||
161 | * | ||
162 | * Note: phys_to_virt(iommu_iova_to_phys(rproc->domain, da)) will work too, | ||
163 | * but only on kernel direct mapped RAM memory. Instead, we're just using | ||
164 | * here the output of the DMA API, which should be more correct. | ||
165 | */ | ||
166 | static void *rproc_da_to_va(struct rproc *rproc, u64 da, int len) | ||
167 | { | ||
168 | struct rproc_mem_entry *carveout; | ||
169 | void *ptr = NULL; | ||
170 | |||
171 | list_for_each_entry(carveout, &rproc->carveouts, node) { | ||
172 | int offset = da - carveout->da; | ||
173 | |||
174 | /* try next carveout if da is too small */ | ||
175 | if (offset < 0) | ||
176 | continue; | ||
177 | |||
178 | /* try next carveout if da is too large */ | ||
179 | if (offset + len > carveout->len) | ||
180 | continue; | ||
181 | |||
182 | ptr = carveout->va + offset; | ||
183 | |||
184 | break; | ||
185 | } | ||
186 | |||
187 | return ptr; | ||
188 | } | ||
189 | |||
190 | /** | ||
191 | * rproc_load_segments() - load firmware segments to memory | ||
192 | * @rproc: remote processor which will be booted using these fw segments | ||
193 | * @elf_data: the content of the ELF firmware image | ||
194 | * | ||
195 | * This function loads the firmware segments to memory, where the remote | ||
196 | * processor expects them. | ||
197 | * | ||
198 | * Some remote processors will expect their code and data to be placed | ||
199 | * in specific device addresses, and can't have them dynamically assigned. | ||
200 | * | ||
201 | * We currently support only those kind of remote processors, and expect | ||
202 | * the program header's paddr member to contain those addresses. We then go | ||
203 | * through the physically contiguous "carveout" memory regions which we | ||
204 | * allocated (and mapped) earlier on behalf of the remote processor, | ||
205 | * and "translate" device address to kernel addresses, so we can copy the | ||
206 | * segments where they are expected. | ||
207 | * | ||
208 | * Currently we only support remote processors that required carveout | ||
209 | * allocations and got them mapped onto their iommus. Some processors | ||
210 | * might be different: they might not have iommus, and would prefer to | ||
211 | * directly allocate memory for every segment/resource. This is not yet | ||
212 | * supported, though. | ||
213 | */ | ||
214 | static int rproc_load_segments(struct rproc *rproc, const u8 *elf_data) | ||
215 | { | ||
216 | struct device *dev = rproc->dev; | ||
217 | struct elf32_hdr *ehdr; | ||
218 | struct elf32_phdr *phdr; | ||
219 | int i, ret = 0; | ||
220 | |||
221 | ehdr = (struct elf32_hdr *)elf_data; | ||
222 | phdr = (struct elf32_phdr *)(elf_data + ehdr->e_phoff); | ||
223 | |||
224 | /* go through the available ELF segments */ | ||
225 | for (i = 0; i < ehdr->e_phnum; i++, phdr++) { | ||
226 | u32 da = phdr->p_paddr; | ||
227 | u32 memsz = phdr->p_memsz; | ||
228 | u32 filesz = phdr->p_filesz; | ||
229 | void *ptr; | ||
230 | |||
231 | if (phdr->p_type != PT_LOAD) | ||
232 | continue; | ||
233 | |||
234 | dev_dbg(dev, "phdr: type %d da 0x%x memsz 0x%x filesz 0x%x\n", | ||
235 | phdr->p_type, da, memsz, filesz); | ||
236 | |||
237 | if (filesz > memsz) { | ||
238 | dev_err(dev, "bad phdr filesz 0x%x memsz 0x%x\n", | ||
239 | filesz, memsz); | ||
240 | ret = -EINVAL; | ||
241 | break; | ||
242 | } | ||
243 | |||
244 | /* grab the kernel address for this device address */ | ||
245 | ptr = rproc_da_to_va(rproc, da, memsz); | ||
246 | if (!ptr) { | ||
247 | dev_err(dev, "bad phdr da 0x%x mem 0x%x\n", da, memsz); | ||
248 | ret = -EINVAL; | ||
249 | break; | ||
250 | } | ||
251 | |||
252 | /* put the segment where the remote processor expects it */ | ||
253 | if (phdr->p_filesz) | ||
254 | memcpy(ptr, elf_data + phdr->p_offset, filesz); | ||
255 | |||
256 | /* | ||
257 | * Zero out remaining memory for this segment. | ||
258 | * | ||
259 | * This isn't strictly required since dma_alloc_coherent already | ||
260 | * did this for us. albeit harmless, we may consider removing | ||
261 | * this. | ||
262 | */ | ||
263 | if (memsz > filesz) | ||
264 | memset(ptr + filesz, 0, memsz - filesz); | ||
265 | } | ||
266 | |||
267 | return ret; | ||
268 | } | ||
269 | |||
270 | /** | ||
271 | * rproc_handle_virtio_hdr() - handle a virtio header resource | ||
272 | * @rproc: the remote processor | ||
273 | * @rsc: the resource descriptor | ||
274 | * | ||
275 | * The existence of this virtio hdr resource entry means that the firmware | ||
276 | * of this @rproc supports this virtio device. | ||
277 | * | ||
278 | * Currently we support only a single virtio device of type VIRTIO_ID_RPMSG, | ||
279 | * but the plan is to remove this limitation and support any number | ||
280 | * of virtio devices (and of any type). We'll also add support for dynamically | ||
281 | * adding (and removing) virtio devices over the rpmsg bus, but small | ||
282 | * firmwares that doesn't want to get involved with rpmsg will be able | ||
283 | * to simple use the resource table for this. | ||
284 | * | ||
285 | * At this point this virtio header entry is rather simple: it just | ||
286 | * announces the virtio device id and the supported virtio device features. | ||
287 | * The plan though is to extend this to include the vring information and | ||
288 | * the virtio config space, too (but first, some resource table overhaul | ||
289 | * is needed: move from fixed-sized to variable-length TLV entries). | ||
290 | * | ||
291 | * For now, the 'flags' member of the resource entry contains the virtio | ||
292 | * device id, the 'da' member contains the device features, and 'pa' is | ||
293 | * where we need to store the guest features once negotiation completes. | ||
294 | * As usual, the 'id' member of this resource contains the index of this | ||
295 | * resource type (i.e. is this the first virtio hdr entry, the 2nd, ...). | ||
296 | * | ||
297 | * Returns 0 on success, or an appropriate error code otherwise | ||
298 | */ | ||
299 | static int rproc_handle_virtio_hdr(struct rproc *rproc, struct fw_resource *rsc) | ||
300 | { | ||
301 | struct rproc_vdev *rvdev; | ||
302 | |||
303 | /* we only support VIRTIO_ID_RPMSG devices for now */ | ||
304 | if (rsc->flags != VIRTIO_ID_RPMSG) { | ||
305 | dev_warn(rproc->dev, "unsupported vdev: %d\n", rsc->flags); | ||
306 | return -EINVAL; | ||
307 | } | ||
308 | |||
309 | /* we only support a single vdev per rproc for now */ | ||
310 | if (rsc->id || rproc->rvdev) { | ||
311 | dev_warn(rproc->dev, "redundant vdev entry: %s\n", rsc->name); | ||
312 | return -EINVAL; | ||
313 | } | ||
314 | |||
315 | rvdev = kzalloc(sizeof(struct rproc_vdev), GFP_KERNEL); | ||
316 | if (!rvdev) | ||
317 | return -ENOMEM; | ||
318 | |||
319 | /* remember the device features */ | ||
320 | rvdev->dfeatures = rsc->da; | ||
321 | |||
322 | rproc->rvdev = rvdev; | ||
323 | rvdev->rproc = rproc; | ||
324 | |||
325 | return 0; | ||
326 | } | ||
327 | |||
328 | /** | ||
329 | * rproc_handle_vring() - handle a vring fw resource | ||
330 | * @rproc: the remote processor | ||
331 | * @rsc: the vring resource descriptor | ||
332 | * | ||
333 | * This resource entry requires allocation of non-cacheable memory | ||
334 | * for a virtio vring. Currently we only support two vrings per remote | ||
335 | * processor, required for the virtio rpmsg device. | ||
336 | * | ||
337 | * The 'len' member of @rsc should contain the number of buffers this vring | ||
338 | * support and 'da' should either contain the device address where | ||
339 | * the remote processor is expecting the vring, or indicate that | ||
340 | * dynamically allocation of the vring's device address is supported. | ||
341 | * | ||
342 | * Note: 'da' is currently not handled. This will be revised when the generic | ||
343 | * iommu-based DMA API will arrive, or a dynanic & non-iommu use case show | ||
344 | * up. Meanwhile, statically-addressed iommu-based images should use | ||
345 | * RSC_DEVMEM resource entries to map their require 'da' to the physical | ||
346 | * address of their base CMA region. | ||
347 | * | ||
348 | * Returns 0 on success, or an appropriate error code otherwise | ||
349 | */ | ||
350 | static int rproc_handle_vring(struct rproc *rproc, struct fw_resource *rsc) | ||
351 | { | ||
352 | struct device *dev = rproc->dev; | ||
353 | struct rproc_vdev *rvdev = rproc->rvdev; | ||
354 | dma_addr_t dma; | ||
355 | int size, id = rsc->id; | ||
356 | void *va; | ||
357 | |||
358 | /* no vdev is in place ? */ | ||
359 | if (!rvdev) { | ||
360 | dev_err(dev, "vring requested without a virtio dev entry\n"); | ||
361 | return -EINVAL; | ||
362 | } | ||
363 | |||
364 | /* the firmware must provide the expected queue size */ | ||
365 | if (!rsc->len) { | ||
366 | dev_err(dev, "missing expected queue size\n"); | ||
367 | return -EINVAL; | ||
368 | } | ||
369 | |||
370 | /* we currently support two vrings per rproc (for rx and tx) */ | ||
371 | if (id >= ARRAY_SIZE(rvdev->vring)) { | ||
372 | dev_err(dev, "%s: invalid vring id %d\n", rsc->name, id); | ||
373 | return -EINVAL; | ||
374 | } | ||
375 | |||
376 | /* have we already allocated this vring id ? */ | ||
377 | if (rvdev->vring[id].len) { | ||
378 | dev_err(dev, "%s: duplicated id %d\n", rsc->name, id); | ||
379 | return -EINVAL; | ||
380 | } | ||
381 | |||
382 | /* actual size of vring (in bytes) */ | ||
383 | size = PAGE_ALIGN(vring_size(rsc->len, AMP_VRING_ALIGN)); | ||
384 | |||
385 | /* | ||
386 | * Allocate non-cacheable memory for the vring. In the future | ||
387 | * this call will also configure the IOMMU for us | ||
388 | */ | ||
389 | va = dma_alloc_coherent(dev, size, &dma, GFP_KERNEL); | ||
390 | if (!va) { | ||
391 | dev_err(dev, "dma_alloc_coherent failed\n"); | ||
392 | return -ENOMEM; | ||
393 | } | ||
394 | |||
395 | dev_dbg(dev, "vring%d: va %p dma %x qsz %d ring size %x\n", id, va, | ||
396 | dma, rsc->len, size); | ||
397 | |||
398 | rvdev->vring[id].len = rsc->len; | ||
399 | rvdev->vring[id].va = va; | ||
400 | rvdev->vring[id].dma = dma; | ||
401 | |||
402 | return 0; | ||
403 | } | ||
404 | |||
405 | /** | ||
406 | * rproc_handle_trace() - handle a shared trace buffer resource | ||
407 | * @rproc: the remote processor | ||
408 | * @rsc: the trace resource descriptor | ||
409 | * | ||
410 | * In case the remote processor dumps trace logs into memory, | ||
411 | * export it via debugfs. | ||
412 | * | ||
413 | * Currently, the 'da' member of @rsc should contain the device address | ||
414 | * where the remote processor is dumping the traces. Later we could also | ||
415 | * support dynamically allocating this address using the generic | ||
416 | * DMA API (but currently there isn't a use case for that). | ||
417 | * | ||
418 | * Returns 0 on success, or an appropriate error code otherwise | ||
419 | */ | ||
420 | static int rproc_handle_trace(struct rproc *rproc, struct fw_resource *rsc) | ||
421 | { | ||
422 | struct rproc_mem_entry *trace; | ||
423 | struct device *dev = rproc->dev; | ||
424 | void *ptr; | ||
425 | char name[15]; | ||
426 | |||
427 | /* what's the kernel address of this resource ? */ | ||
428 | ptr = rproc_da_to_va(rproc, rsc->da, rsc->len); | ||
429 | if (!ptr) { | ||
430 | dev_err(dev, "erroneous trace resource entry\n"); | ||
431 | return -EINVAL; | ||
432 | } | ||
433 | |||
434 | trace = kzalloc(sizeof(*trace), GFP_KERNEL); | ||
435 | if (!trace) { | ||
436 | dev_err(dev, "kzalloc trace failed\n"); | ||
437 | return -ENOMEM; | ||
438 | } | ||
439 | |||
440 | /* set the trace buffer dma properties */ | ||
441 | trace->len = rsc->len; | ||
442 | trace->va = ptr; | ||
443 | |||
444 | /* make sure snprintf always null terminates, even if truncating */ | ||
445 | snprintf(name, sizeof(name), "trace%d", rproc->num_traces); | ||
446 | |||
447 | /* create the debugfs entry */ | ||
448 | trace->priv = rproc_create_trace_file(name, rproc, trace); | ||
449 | if (!trace->priv) { | ||
450 | trace->va = NULL; | ||
451 | kfree(trace); | ||
452 | return -EINVAL; | ||
453 | } | ||
454 | |||
455 | list_add_tail(&trace->node, &rproc->traces); | ||
456 | |||
457 | rproc->num_traces++; | ||
458 | |||
459 | dev_dbg(dev, "%s added: va %p, da 0x%llx, len 0x%x\n", name, ptr, | ||
460 | rsc->da, rsc->len); | ||
461 | |||
462 | return 0; | ||
463 | } | ||
464 | |||
465 | /** | ||
466 | * rproc_handle_devmem() - handle devmem resource entry | ||
467 | * @rproc: remote processor handle | ||
468 | * @rsc: the devmem resource entry | ||
469 | * | ||
470 | * Remote processors commonly need to access certain on-chip peripherals. | ||
471 | * | ||
472 | * Some of these remote processors access memory via an iommu device, | ||
473 | * and might require us to configure their iommu before they can access | ||
474 | * the on-chip peripherals they need. | ||
475 | * | ||
476 | * This resource entry is a request to map such a peripheral device. | ||
477 | * | ||
478 | * These devmem entries will contain the physical address of the device in | ||
479 | * the 'pa' member. If a specific device address is expected, then 'da' will | ||
480 | * contain it (currently this is the only use case supported). 'len' will | ||
481 | * contain the size of the physical region we need to map. | ||
482 | * | ||
483 | * Currently we just "trust" those devmem entries to contain valid physical | ||
484 | * addresses, but this is going to change: we want the implementations to | ||
485 | * tell us ranges of physical addresses the firmware is allowed to request, | ||
486 | * and not allow firmwares to request access to physical addresses that | ||
487 | * are outside those ranges. | ||
488 | */ | ||
489 | static int rproc_handle_devmem(struct rproc *rproc, struct fw_resource *rsc) | ||
490 | { | ||
491 | struct rproc_mem_entry *mapping; | ||
492 | int ret; | ||
493 | |||
494 | /* no point in handling this resource without a valid iommu domain */ | ||
495 | if (!rproc->domain) | ||
496 | return -EINVAL; | ||
497 | |||
498 | mapping = kzalloc(sizeof(*mapping), GFP_KERNEL); | ||
499 | if (!mapping) { | ||
500 | dev_err(rproc->dev, "kzalloc mapping failed\n"); | ||
501 | return -ENOMEM; | ||
502 | } | ||
503 | |||
504 | ret = iommu_map(rproc->domain, rsc->da, rsc->pa, rsc->len, rsc->flags); | ||
505 | if (ret) { | ||
506 | dev_err(rproc->dev, "failed to map devmem: %d\n", ret); | ||
507 | goto out; | ||
508 | } | ||
509 | |||
510 | /* | ||
511 | * We'll need this info later when we'll want to unmap everything | ||
512 | * (e.g. on shutdown). | ||
513 | * | ||
514 | * We can't trust the remote processor not to change the resource | ||
515 | * table, so we must maintain this info independently. | ||
516 | */ | ||
517 | mapping->da = rsc->da; | ||
518 | mapping->len = rsc->len; | ||
519 | list_add_tail(&mapping->node, &rproc->mappings); | ||
520 | |||
521 | dev_dbg(rproc->dev, "mapped devmem pa 0x%llx, da 0x%llx, len 0x%x\n", | ||
522 | rsc->pa, rsc->da, rsc->len); | ||
523 | |||
524 | return 0; | ||
525 | |||
526 | out: | ||
527 | kfree(mapping); | ||
528 | return ret; | ||
529 | } | ||
530 | |||
531 | /** | ||
532 | * rproc_handle_carveout() - handle phys contig memory allocation requests | ||
533 | * @rproc: rproc handle | ||
534 | * @rsc: the resource entry | ||
535 | * | ||
536 | * This function will handle firmware requests for allocation of physically | ||
537 | * contiguous memory regions. | ||
538 | * | ||
539 | * These request entries should come first in the firmware's resource table, | ||
540 | * as other firmware entries might request placing other data objects inside | ||
541 | * these memory regions (e.g. data/code segments, trace resource entries, ...). | ||
542 | * | ||
543 | * Allocating memory this way helps utilizing the reserved physical memory | ||
544 | * (e.g. CMA) more efficiently, and also minimizes the number of TLB entries | ||
545 | * needed to map it (in case @rproc is using an IOMMU). Reducing the TLB | ||
546 | * pressure is important; it may have a substantial impact on performance. | ||
547 | */ | ||
548 | static int rproc_handle_carveout(struct rproc *rproc, struct fw_resource *rsc) | ||
549 | { | ||
550 | struct rproc_mem_entry *carveout, *mapping; | ||
551 | struct device *dev = rproc->dev; | ||
552 | dma_addr_t dma; | ||
553 | void *va; | ||
554 | int ret; | ||
555 | |||
556 | mapping = kzalloc(sizeof(*mapping), GFP_KERNEL); | ||
557 | if (!mapping) { | ||
558 | dev_err(dev, "kzalloc mapping failed\n"); | ||
559 | return -ENOMEM; | ||
560 | } | ||
561 | |||
562 | carveout = kzalloc(sizeof(*carveout), GFP_KERNEL); | ||
563 | if (!carveout) { | ||
564 | dev_err(dev, "kzalloc carveout failed\n"); | ||
565 | ret = -ENOMEM; | ||
566 | goto free_mapping; | ||
567 | } | ||
568 | |||
569 | va = dma_alloc_coherent(dev, rsc->len, &dma, GFP_KERNEL); | ||
570 | if (!va) { | ||
571 | dev_err(dev, "failed to dma alloc carveout: %d\n", rsc->len); | ||
572 | ret = -ENOMEM; | ||
573 | goto free_carv; | ||
574 | } | ||
575 | |||
576 | dev_dbg(dev, "carveout va %p, dma %x, len 0x%x\n", va, dma, rsc->len); | ||
577 | |||
578 | /* | ||
579 | * Ok, this is non-standard. | ||
580 | * | ||
581 | * Sometimes we can't rely on the generic iommu-based DMA API | ||
582 | * to dynamically allocate the device address and then set the IOMMU | ||
583 | * tables accordingly, because some remote processors might | ||
584 | * _require_ us to use hard coded device addresses that their | ||
585 | * firmware was compiled with. | ||
586 | * | ||
587 | * In this case, we must use the IOMMU API directly and map | ||
588 | * the memory to the device address as expected by the remote | ||
589 | * processor. | ||
590 | * | ||
591 | * Obviously such remote processor devices should not be configured | ||
592 | * to use the iommu-based DMA API: we expect 'dma' to contain the | ||
593 | * physical address in this case. | ||
594 | */ | ||
595 | if (rproc->domain) { | ||
596 | ret = iommu_map(rproc->domain, rsc->da, dma, rsc->len, | ||
597 | rsc->flags); | ||
598 | if (ret) { | ||
599 | dev_err(dev, "iommu_map failed: %d\n", ret); | ||
600 | goto dma_free; | ||
601 | } | ||
602 | |||
603 | /* | ||
604 | * We'll need this info later when we'll want to unmap | ||
605 | * everything (e.g. on shutdown). | ||
606 | * | ||
607 | * We can't trust the remote processor not to change the | ||
608 | * resource table, so we must maintain this info independently. | ||
609 | */ | ||
610 | mapping->da = rsc->da; | ||
611 | mapping->len = rsc->len; | ||
612 | list_add_tail(&mapping->node, &rproc->mappings); | ||
613 | |||
614 | dev_dbg(dev, "carveout mapped 0x%llx to 0x%x\n", rsc->da, dma); | ||
615 | |||
616 | /* | ||
617 | * Some remote processors might need to know the pa | ||
618 | * even though they are behind an IOMMU. E.g., OMAP4's | ||
619 | * remote M3 processor needs this so it can control | ||
620 | * on-chip hardware accelerators that are not behind | ||
621 | * the IOMMU, and therefor must know the pa. | ||
622 | * | ||
623 | * Generally we don't want to expose physical addresses | ||
624 | * if we don't have to (remote processors are generally | ||
625 | * _not_ trusted), so we might want to do this only for | ||
626 | * remote processor that _must_ have this (e.g. OMAP4's | ||
627 | * dual M3 subsystem). | ||
628 | */ | ||
629 | rsc->pa = dma; | ||
630 | } | ||
631 | |||
632 | carveout->va = va; | ||
633 | carveout->len = rsc->len; | ||
634 | carveout->dma = dma; | ||
635 | carveout->da = rsc->da; | ||
636 | |||
637 | list_add_tail(&carveout->node, &rproc->carveouts); | ||
638 | |||
639 | return 0; | ||
640 | |||
641 | dma_free: | ||
642 | dma_free_coherent(dev, rsc->len, va, dma); | ||
643 | free_carv: | ||
644 | kfree(carveout); | ||
645 | free_mapping: | ||
646 | kfree(mapping); | ||
647 | return ret; | ||
648 | } | ||
649 | |||
650 | /* handle firmware resource entries before booting the remote processor */ | ||
651 | static int | ||
652 | rproc_handle_boot_rsc(struct rproc *rproc, struct fw_resource *rsc, int len) | ||
653 | { | ||
654 | struct device *dev = rproc->dev; | ||
655 | int ret = 0; | ||
656 | |||
657 | while (len >= sizeof(*rsc)) { | ||
658 | dev_dbg(dev, "rsc: type %d, da 0x%llx, pa 0x%llx, len 0x%x, " | ||
659 | "id %d, name %s, flags %x\n", rsc->type, rsc->da, | ||
660 | rsc->pa, rsc->len, rsc->id, rsc->name, rsc->flags); | ||
661 | |||
662 | switch (rsc->type) { | ||
663 | case RSC_CARVEOUT: | ||
664 | ret = rproc_handle_carveout(rproc, rsc); | ||
665 | break; | ||
666 | case RSC_DEVMEM: | ||
667 | ret = rproc_handle_devmem(rproc, rsc); | ||
668 | break; | ||
669 | case RSC_TRACE: | ||
670 | ret = rproc_handle_trace(rproc, rsc); | ||
671 | break; | ||
672 | case RSC_VRING: | ||
673 | ret = rproc_handle_vring(rproc, rsc); | ||
674 | break; | ||
675 | case RSC_VIRTIO_DEV: | ||
676 | /* this one is handled early upon registration */ | ||
677 | break; | ||
678 | default: | ||
679 | dev_warn(dev, "unsupported resource %d\n", rsc->type); | ||
680 | break; | ||
681 | } | ||
682 | |||
683 | if (ret) | ||
684 | break; | ||
685 | |||
686 | rsc++; | ||
687 | len -= sizeof(*rsc); | ||
688 | } | ||
689 | |||
690 | return ret; | ||
691 | } | ||
692 | |||
693 | /* handle firmware resource entries while registering the remote processor */ | ||
694 | static int | ||
695 | rproc_handle_virtio_rsc(struct rproc *rproc, struct fw_resource *rsc, int len) | ||
696 | { | ||
697 | struct device *dev = rproc->dev; | ||
698 | int ret = 0; | ||
699 | |||
700 | for (; len >= sizeof(*rsc); rsc++, len -= sizeof(*rsc)) | ||
701 | if (rsc->type == RSC_VIRTIO_DEV) { | ||
702 | dev_dbg(dev, "found vdev %d/%s features %llx\n", | ||
703 | rsc->flags, rsc->name, rsc->da); | ||
704 | ret = rproc_handle_virtio_hdr(rproc, rsc); | ||
705 | break; | ||
706 | } | ||
707 | |||
708 | return ret; | ||
709 | } | ||
710 | |||
711 | /** | ||
712 | * rproc_handle_resources() - find and handle the resource table | ||
713 | * @rproc: the rproc handle | ||
714 | * @elf_data: the content of the ELF firmware image | ||
715 | * @handler: function that should be used to handle the resource table | ||
716 | * | ||
717 | * This function finds the resource table inside the remote processor's | ||
718 | * firmware, and invoke a user-supplied handler with it (we have two | ||
719 | * possible handlers: one is invoked upon registration of @rproc, | ||
720 | * in order to register the supported virito devices, and the other is | ||
721 | * invoked when @rproc is actually booted). | ||
722 | * | ||
723 | * Currently this function fails if a resource table doesn't exist. | ||
724 | * This restriction will be removed when we'll start supporting remote | ||
725 | * processors that don't need a resource table. | ||
726 | */ | ||
727 | static int rproc_handle_resources(struct rproc *rproc, const u8 *elf_data, | ||
728 | rproc_handle_resources_t handler) | ||
729 | |||
730 | { | ||
731 | struct elf32_hdr *ehdr; | ||
732 | struct elf32_shdr *shdr; | ||
733 | const char *name_table; | ||
734 | int i, ret = -EINVAL; | ||
735 | |||
736 | ehdr = (struct elf32_hdr *)elf_data; | ||
737 | shdr = (struct elf32_shdr *)(elf_data + ehdr->e_shoff); | ||
738 | name_table = elf_data + shdr[ehdr->e_shstrndx].sh_offset; | ||
739 | |||
740 | /* look for the resource table and handle it */ | ||
741 | for (i = 0; i < ehdr->e_shnum; i++, shdr++) { | ||
742 | if (!strcmp(name_table + shdr->sh_name, ".resource_table")) { | ||
743 | struct fw_resource *table = (struct fw_resource *) | ||
744 | (elf_data + shdr->sh_offset); | ||
745 | |||
746 | ret = handler(rproc, table, shdr->sh_size); | ||
747 | |||
748 | break; | ||
749 | } | ||
750 | } | ||
751 | |||
752 | return ret; | ||
753 | } | ||
754 | |||
755 | /** | ||
756 | * rproc_resource_cleanup() - clean up and free all acquired resources | ||
757 | * @rproc: rproc handle | ||
758 | * | ||
759 | * This function will free all resources acquired for @rproc, and it | ||
760 | * is called when @rproc shuts down, or just failed booting. | ||
761 | */ | ||
762 | static void rproc_resource_cleanup(struct rproc *rproc) | ||
763 | { | ||
764 | struct rproc_mem_entry *entry, *tmp; | ||
765 | struct device *dev = rproc->dev; | ||
766 | struct rproc_vdev *rvdev = rproc->rvdev; | ||
767 | int i; | ||
768 | |||
769 | /* clean up debugfs trace entries */ | ||
770 | list_for_each_entry_safe(entry, tmp, &rproc->traces, node) { | ||
771 | rproc_remove_trace_file(entry->priv); | ||
772 | rproc->num_traces--; | ||
773 | list_del(&entry->node); | ||
774 | kfree(entry); | ||
775 | } | ||
776 | |||
777 | /* free the coherent memory allocated for the vrings */ | ||
778 | for (i = 0; rvdev && i < ARRAY_SIZE(rvdev->vring); i++) { | ||
779 | int qsz = rvdev->vring[i].len; | ||
780 | void *va = rvdev->vring[i].va; | ||
781 | int dma = rvdev->vring[i].dma; | ||
782 | |||
783 | /* virtqueue size is expressed in number of buffers supported */ | ||
784 | if (qsz) { | ||
785 | /* how many bytes does this vring really occupy ? */ | ||
786 | int size = PAGE_ALIGN(vring_size(qsz, AMP_VRING_ALIGN)); | ||
787 | |||
788 | dma_free_coherent(rproc->dev, size, va, dma); | ||
789 | |||
790 | rvdev->vring[i].len = 0; | ||
791 | } | ||
792 | } | ||
793 | |||
794 | /* clean up carveout allocations */ | ||
795 | list_for_each_entry_safe(entry, tmp, &rproc->carveouts, node) { | ||
796 | dma_free_coherent(dev, entry->len, entry->va, entry->dma); | ||
797 | list_del(&entry->node); | ||
798 | kfree(entry); | ||
799 | } | ||
800 | |||
801 | /* clean up iommu mapping entries */ | ||
802 | list_for_each_entry_safe(entry, tmp, &rproc->mappings, node) { | ||
803 | size_t unmapped; | ||
804 | |||
805 | unmapped = iommu_unmap(rproc->domain, entry->da, entry->len); | ||
806 | if (unmapped != entry->len) { | ||
807 | /* nothing much to do besides complaining */ | ||
808 | dev_err(dev, "failed to unmap %u/%u\n", entry->len, | ||
809 | unmapped); | ||
810 | } | ||
811 | |||
812 | list_del(&entry->node); | ||
813 | kfree(entry); | ||
814 | } | ||
815 | } | ||
816 | |||
817 | /* make sure this fw image is sane */ | ||
818 | static int rproc_fw_sanity_check(struct rproc *rproc, const struct firmware *fw) | ||
819 | { | ||
820 | const char *name = rproc->firmware; | ||
821 | struct device *dev = rproc->dev; | ||
822 | struct elf32_hdr *ehdr; | ||
823 | |||
824 | if (!fw) { | ||
825 | dev_err(dev, "failed to load %s\n", name); | ||
826 | return -EINVAL; | ||
827 | } | ||
828 | |||
829 | if (fw->size < sizeof(struct elf32_hdr)) { | ||
830 | dev_err(dev, "Image is too small\n"); | ||
831 | return -EINVAL; | ||
832 | } | ||
833 | |||
834 | ehdr = (struct elf32_hdr *)fw->data; | ||
835 | |||
836 | if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) { | ||
837 | dev_err(dev, "Image is corrupted (bad magic)\n"); | ||
838 | return -EINVAL; | ||
839 | } | ||
840 | |||
841 | if (ehdr->e_phnum == 0) { | ||
842 | dev_err(dev, "No loadable segments\n"); | ||
843 | return -EINVAL; | ||
844 | } | ||
845 | |||
846 | if (ehdr->e_phoff > fw->size) { | ||
847 | dev_err(dev, "Firmware size is too small\n"); | ||
848 | return -EINVAL; | ||
849 | } | ||
850 | |||
851 | return 0; | ||
852 | } | ||
853 | |||
854 | /* | ||
855 | * take a firmware and boot a remote processor with it. | ||
856 | */ | ||
857 | static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw) | ||
858 | { | ||
859 | struct device *dev = rproc->dev; | ||
860 | const char *name = rproc->firmware; | ||
861 | struct elf32_hdr *ehdr; | ||
862 | int ret; | ||
863 | |||
864 | ret = rproc_fw_sanity_check(rproc, fw); | ||
865 | if (ret) | ||
866 | return ret; | ||
867 | |||
868 | ehdr = (struct elf32_hdr *)fw->data; | ||
869 | |||
870 | dev_info(dev, "Booting fw image %s, size %d\n", name, fw->size); | ||
871 | |||
872 | /* | ||
873 | * if enabling an IOMMU isn't relevant for this rproc, this is | ||
874 | * just a nop | ||
875 | */ | ||
876 | ret = rproc_enable_iommu(rproc); | ||
877 | if (ret) { | ||
878 | dev_err(dev, "can't enable iommu: %d\n", ret); | ||
879 | return ret; | ||
880 | } | ||
881 | |||
882 | /* | ||
883 | * The ELF entry point is the rproc's boot addr (though this is not | ||
884 | * a configurable property of all remote processors: some will always | ||
885 | * boot at a specific hardcoded address). | ||
886 | */ | ||
887 | rproc->bootaddr = ehdr->e_entry; | ||
888 | |||
889 | /* handle fw resources which are required to boot rproc */ | ||
890 | ret = rproc_handle_resources(rproc, fw->data, rproc_handle_boot_rsc); | ||
891 | if (ret) { | ||
892 | dev_err(dev, "Failed to process resources: %d\n", ret); | ||
893 | goto clean_up; | ||
894 | } | ||
895 | |||
896 | /* load the ELF segments to memory */ | ||
897 | ret = rproc_load_segments(rproc, fw->data); | ||
898 | if (ret) { | ||
899 | dev_err(dev, "Failed to load program segments: %d\n", ret); | ||
900 | goto clean_up; | ||
901 | } | ||
902 | |||
903 | /* power up the remote processor */ | ||
904 | ret = rproc->ops->start(rproc); | ||
905 | if (ret) { | ||
906 | dev_err(dev, "can't start rproc %s: %d\n", rproc->name, ret); | ||
907 | goto clean_up; | ||
908 | } | ||
909 | |||
910 | rproc->state = RPROC_RUNNING; | ||
911 | |||
912 | dev_info(dev, "remote processor %s is now up\n", rproc->name); | ||
913 | |||
914 | return 0; | ||
915 | |||
916 | clean_up: | ||
917 | rproc_resource_cleanup(rproc); | ||
918 | rproc_disable_iommu(rproc); | ||
919 | return ret; | ||
920 | } | ||
921 | |||
922 | /* | ||
923 | * take a firmware and look for virtio devices to register. | ||
924 | * | ||
925 | * Note: this function is called asynchronously upon registration of the | ||
926 | * remote processor (so we must wait until it completes before we try | ||
927 | * to unregister the device. one other option is just to use kref here, | ||
928 | * that might be cleaner). | ||
929 | */ | ||
930 | static void rproc_fw_config_virtio(const struct firmware *fw, void *context) | ||
931 | { | ||
932 | struct rproc *rproc = context; | ||
933 | struct device *dev = rproc->dev; | ||
934 | int ret; | ||
935 | |||
936 | if (rproc_fw_sanity_check(rproc, fw) < 0) | ||
937 | goto out; | ||
938 | |||
939 | /* does the fw supports any virtio devices ? */ | ||
940 | ret = rproc_handle_resources(rproc, fw->data, rproc_handle_virtio_rsc); | ||
941 | if (ret) { | ||
942 | dev_info(dev, "No fw virtio device was found\n"); | ||
943 | goto out; | ||
944 | } | ||
945 | |||
946 | /* add the virtio device (currently only rpmsg vdevs are supported) */ | ||
947 | ret = rproc_add_rpmsg_vdev(rproc); | ||
948 | if (ret) | ||
949 | goto out; | ||
950 | |||
951 | out: | ||
952 | if (fw) | ||
953 | release_firmware(fw); | ||
954 | /* allow rproc_unregister() contexts, if any, to proceed */ | ||
955 | complete_all(&rproc->firmware_loading_complete); | ||
956 | } | ||
957 | |||
958 | /** | ||
959 | * rproc_boot() - boot a remote processor | ||
960 | * @rproc: handle of a remote processor | ||
961 | * | ||
962 | * Boot a remote processor (i.e. load its firmware, power it on, ...). | ||
963 | * | ||
964 | * If the remote processor is already powered on, this function immediately | ||
965 | * returns (successfully). | ||
966 | * | ||
967 | * Returns 0 on success, and an appropriate error value otherwise. | ||
968 | */ | ||
969 | int rproc_boot(struct rproc *rproc) | ||
970 | { | ||
971 | const struct firmware *firmware_p; | ||
972 | struct device *dev; | ||
973 | int ret; | ||
974 | |||
975 | if (!rproc) { | ||
976 | pr_err("invalid rproc handle\n"); | ||
977 | return -EINVAL; | ||
978 | } | ||
979 | |||
980 | dev = rproc->dev; | ||
981 | |||
982 | ret = mutex_lock_interruptible(&rproc->lock); | ||
983 | if (ret) { | ||
984 | dev_err(dev, "can't lock rproc %s: %d\n", rproc->name, ret); | ||
985 | return ret; | ||
986 | } | ||
987 | |||
988 | /* loading a firmware is required */ | ||
989 | if (!rproc->firmware) { | ||
990 | dev_err(dev, "%s: no firmware to load\n", __func__); | ||
991 | ret = -EINVAL; | ||
992 | goto unlock_mutex; | ||
993 | } | ||
994 | |||
995 | /* prevent underlying implementation from being removed */ | ||
996 | if (!try_module_get(dev->driver->owner)) { | ||
997 | dev_err(dev, "%s: can't get owner\n", __func__); | ||
998 | ret = -EINVAL; | ||
999 | goto unlock_mutex; | ||
1000 | } | ||
1001 | |||
1002 | /* skip the boot process if rproc is already powered up */ | ||
1003 | if (atomic_inc_return(&rproc->power) > 1) { | ||
1004 | ret = 0; | ||
1005 | goto unlock_mutex; | ||
1006 | } | ||
1007 | |||
1008 | dev_info(dev, "powering up %s\n", rproc->name); | ||
1009 | |||
1010 | /* load firmware */ | ||
1011 | ret = request_firmware(&firmware_p, rproc->firmware, dev); | ||
1012 | if (ret < 0) { | ||
1013 | dev_err(dev, "request_firmware failed: %d\n", ret); | ||
1014 | goto downref_rproc; | ||
1015 | } | ||
1016 | |||
1017 | ret = rproc_fw_boot(rproc, firmware_p); | ||
1018 | |||
1019 | release_firmware(firmware_p); | ||
1020 | |||
1021 | downref_rproc: | ||
1022 | if (ret) { | ||
1023 | module_put(dev->driver->owner); | ||
1024 | atomic_dec(&rproc->power); | ||
1025 | } | ||
1026 | unlock_mutex: | ||
1027 | mutex_unlock(&rproc->lock); | ||
1028 | return ret; | ||
1029 | } | ||
1030 | EXPORT_SYMBOL(rproc_boot); | ||
1031 | |||
1032 | /** | ||
1033 | * rproc_shutdown() - power off the remote processor | ||
1034 | * @rproc: the remote processor | ||
1035 | * | ||
1036 | * Power off a remote processor (previously booted with rproc_boot()). | ||
1037 | * | ||
1038 | * In case @rproc is still being used by an additional user(s), then | ||
1039 | * this function will just decrement the power refcount and exit, | ||
1040 | * without really powering off the device. | ||
1041 | * | ||
1042 | * Every call to rproc_boot() must (eventually) be accompanied by a call | ||
1043 | * to rproc_shutdown(). Calling rproc_shutdown() redundantly is a bug. | ||
1044 | * | ||
1045 | * Notes: | ||
1046 | * - we're not decrementing the rproc's refcount, only the power refcount. | ||
1047 | * which means that the @rproc handle stays valid even after rproc_shutdown() | ||
1048 | * returns, and users can still use it with a subsequent rproc_boot(), if | ||
1049 | * needed. | ||
1050 | * - don't call rproc_shutdown() to unroll rproc_get_by_name(), exactly | ||
1051 | * because rproc_shutdown() _does not_ decrement the refcount of @rproc. | ||
1052 | * To decrement the refcount of @rproc, use rproc_put() (but _only_ if | ||
1053 | * you acquired @rproc using rproc_get_by_name()). | ||
1054 | */ | ||
1055 | void rproc_shutdown(struct rproc *rproc) | ||
1056 | { | ||
1057 | struct device *dev = rproc->dev; | ||
1058 | int ret; | ||
1059 | |||
1060 | ret = mutex_lock_interruptible(&rproc->lock); | ||
1061 | if (ret) { | ||
1062 | dev_err(dev, "can't lock rproc %s: %d\n", rproc->name, ret); | ||
1063 | return; | ||
1064 | } | ||
1065 | |||
1066 | /* if the remote proc is still needed, bail out */ | ||
1067 | if (!atomic_dec_and_test(&rproc->power)) | ||
1068 | goto out; | ||
1069 | |||
1070 | /* power off the remote processor */ | ||
1071 | ret = rproc->ops->stop(rproc); | ||
1072 | if (ret) { | ||
1073 | atomic_inc(&rproc->power); | ||
1074 | dev_err(dev, "can't stop rproc: %d\n", ret); | ||
1075 | goto out; | ||
1076 | } | ||
1077 | |||
1078 | /* clean up all acquired resources */ | ||
1079 | rproc_resource_cleanup(rproc); | ||
1080 | |||
1081 | rproc_disable_iommu(rproc); | ||
1082 | |||
1083 | rproc->state = RPROC_OFFLINE; | ||
1084 | |||
1085 | dev_info(dev, "stopped remote processor %s\n", rproc->name); | ||
1086 | |||
1087 | out: | ||
1088 | mutex_unlock(&rproc->lock); | ||
1089 | if (!ret) | ||
1090 | module_put(dev->driver->owner); | ||
1091 | } | ||
1092 | EXPORT_SYMBOL(rproc_shutdown); | ||
1093 | |||
1094 | /** | ||
1095 | * rproc_release() - completely deletes the existence of a remote processor | ||
1096 | * @kref: the rproc's kref | ||
1097 | * | ||
1098 | * This function should _never_ be called directly. | ||
1099 | * | ||
1100 | * The only reasonable location to use it is as an argument when kref_put'ing | ||
1101 | * @rproc's refcount. | ||
1102 | * | ||
1103 | * This way it will be called when no one holds a valid pointer to this @rproc | ||
1104 | * anymore (and obviously after it is removed from the rprocs klist). | ||
1105 | * | ||
1106 | * Note: this function is not static because rproc_vdev_release() needs it when | ||
1107 | * it decrements @rproc's refcount. | ||
1108 | */ | ||
1109 | void rproc_release(struct kref *kref) | ||
1110 | { | ||
1111 | struct rproc *rproc = container_of(kref, struct rproc, refcount); | ||
1112 | |||
1113 | dev_info(rproc->dev, "removing %s\n", rproc->name); | ||
1114 | |||
1115 | rproc_delete_debug_dir(rproc); | ||
1116 | |||
1117 | /* at this point no one holds a reference to rproc anymore */ | ||
1118 | kfree(rproc); | ||
1119 | } | ||
1120 | |||
1121 | /* will be called when an rproc is added to the rprocs klist */ | ||
1122 | static void klist_rproc_get(struct klist_node *n) | ||
1123 | { | ||
1124 | struct rproc *rproc = container_of(n, struct rproc, node); | ||
1125 | |||
1126 | kref_get(&rproc->refcount); | ||
1127 | } | ||
1128 | |||
1129 | /* will be called when an rproc is removed from the rprocs klist */ | ||
1130 | static void klist_rproc_put(struct klist_node *n) | ||
1131 | { | ||
1132 | struct rproc *rproc = container_of(n, struct rproc, node); | ||
1133 | |||
1134 | kref_put(&rproc->refcount, rproc_release); | ||
1135 | } | ||
1136 | |||
1137 | static struct rproc *next_rproc(struct klist_iter *i) | ||
1138 | { | ||
1139 | struct klist_node *n; | ||
1140 | |||
1141 | n = klist_next(i); | ||
1142 | if (!n) | ||
1143 | return NULL; | ||
1144 | |||
1145 | return container_of(n, struct rproc, node); | ||
1146 | } | ||
1147 | |||
1148 | /** | ||
1149 | * rproc_get_by_name() - find a remote processor by name and boot it | ||
1150 | * @name: name of the remote processor | ||
1151 | * | ||
1152 | * Finds an rproc handle using the remote processor's name, and then | ||
1153 | * boot it. If it's already powered on, then just immediately return | ||
1154 | * (successfully). | ||
1155 | * | ||
1156 | * Returns the rproc handle on success, and NULL on failure. | ||
1157 | * | ||
1158 | * This function increments the remote processor's refcount, so always | ||
1159 | * use rproc_put() to decrement it back once rproc isn't needed anymore. | ||
1160 | * | ||
1161 | * Note: currently this function (and its counterpart rproc_put()) are not | ||
1162 | * used anymore by the rpmsg subsystem. We need to scrutinize the use cases | ||
1163 | * that still need them, and see if we can migrate them to use the non | ||
1164 | * name-based boot/shutdown interface. | ||
1165 | */ | ||
1166 | struct rproc *rproc_get_by_name(const char *name) | ||
1167 | { | ||
1168 | struct rproc *rproc; | ||
1169 | struct klist_iter i; | ||
1170 | int ret; | ||
1171 | |||
1172 | /* find the remote processor, and upref its refcount */ | ||
1173 | klist_iter_init(&rprocs, &i); | ||
1174 | while ((rproc = next_rproc(&i)) != NULL) | ||
1175 | if (!strcmp(rproc->name, name)) { | ||
1176 | kref_get(&rproc->refcount); | ||
1177 | break; | ||
1178 | } | ||
1179 | klist_iter_exit(&i); | ||
1180 | |||
1181 | /* can't find this rproc ? */ | ||
1182 | if (!rproc) { | ||
1183 | pr_err("can't find remote processor %s\n", name); | ||
1184 | return NULL; | ||
1185 | } | ||
1186 | |||
1187 | ret = rproc_boot(rproc); | ||
1188 | if (ret < 0) { | ||
1189 | kref_put(&rproc->refcount, rproc_release); | ||
1190 | return NULL; | ||
1191 | } | ||
1192 | |||
1193 | return rproc; | ||
1194 | } | ||
1195 | EXPORT_SYMBOL(rproc_get_by_name); | ||
1196 | |||
1197 | /** | ||
1198 | * rproc_put() - decrement the refcount of a remote processor, and shut it down | ||
1199 | * @rproc: the remote processor | ||
1200 | * | ||
1201 | * This function tries to shutdown @rproc, and it then decrements its | ||
1202 | * refcount. | ||
1203 | * | ||
1204 | * After this function returns, @rproc may _not_ be used anymore, and its | ||
1205 | * handle should be considered invalid. | ||
1206 | * | ||
1207 | * This function should be called _iff_ the @rproc handle was grabbed by | ||
1208 | * calling rproc_get_by_name(). | ||
1209 | */ | ||
1210 | void rproc_put(struct rproc *rproc) | ||
1211 | { | ||
1212 | /* try to power off the remote processor */ | ||
1213 | rproc_shutdown(rproc); | ||
1214 | |||
1215 | /* downref rproc's refcount */ | ||
1216 | kref_put(&rproc->refcount, rproc_release); | ||
1217 | } | ||
1218 | EXPORT_SYMBOL(rproc_put); | ||
1219 | |||
1220 | /** | ||
1221 | * rproc_register() - register a remote processor | ||
1222 | * @rproc: the remote processor handle to register | ||
1223 | * | ||
1224 | * Registers @rproc with the remoteproc framework, after it has been | ||
1225 | * allocated with rproc_alloc(). | ||
1226 | * | ||
1227 | * This is called by the platform-specific rproc implementation, whenever | ||
1228 | * a new remote processor device is probed. | ||
1229 | * | ||
1230 | * Returns 0 on success and an appropriate error code otherwise. | ||
1231 | * | ||
1232 | * Note: this function initiates an asynchronous firmware loading | ||
1233 | * context, which will look for virtio devices supported by the rproc's | ||
1234 | * firmware. | ||
1235 | * | ||
1236 | * If found, those virtio devices will be created and added, so as a result | ||
1237 | * of registering this remote processor, additional virtio drivers will be | ||
1238 | * probed. | ||
1239 | * | ||
1240 | * Currently, though, we only support a single RPMSG virtio vdev per remote | ||
1241 | * processor. | ||
1242 | */ | ||
1243 | int rproc_register(struct rproc *rproc) | ||
1244 | { | ||
1245 | struct device *dev = rproc->dev; | ||
1246 | int ret = 0; | ||
1247 | |||
1248 | /* expose to rproc_get_by_name users */ | ||
1249 | klist_add_tail(&rproc->node, &rprocs); | ||
1250 | |||
1251 | dev_info(rproc->dev, "%s is available\n", rproc->name); | ||
1252 | |||
1253 | /* create debugfs entries */ | ||
1254 | rproc_create_debug_dir(rproc); | ||
1255 | |||
1256 | /* rproc_unregister() calls must wait until async loader completes */ | ||
1257 | init_completion(&rproc->firmware_loading_complete); | ||
1258 | |||
1259 | /* | ||
1260 | * We must retrieve early virtio configuration info from | ||
1261 | * the firmware (e.g. whether to register a virtio rpmsg device, | ||
1262 | * what virtio features does it support, ...). | ||
1263 | * | ||
1264 | * We're initiating an asynchronous firmware loading, so we can | ||
1265 | * be built-in kernel code, without hanging the boot process. | ||
1266 | */ | ||
1267 | ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, | ||
1268 | rproc->firmware, dev, GFP_KERNEL, | ||
1269 | rproc, rproc_fw_config_virtio); | ||
1270 | if (ret < 0) { | ||
1271 | dev_err(dev, "request_firmware_nowait failed: %d\n", ret); | ||
1272 | complete_all(&rproc->firmware_loading_complete); | ||
1273 | klist_remove(&rproc->node); | ||
1274 | } | ||
1275 | |||
1276 | return ret; | ||
1277 | } | ||
1278 | EXPORT_SYMBOL(rproc_register); | ||
1279 | |||
1280 | /** | ||
1281 | * rproc_alloc() - allocate a remote processor handle | ||
1282 | * @dev: the underlying device | ||
1283 | * @name: name of this remote processor | ||
1284 | * @ops: platform-specific handlers (mainly start/stop) | ||
1285 | * @firmware: name of firmware file to load | ||
1286 | * @len: length of private data needed by the rproc driver (in bytes) | ||
1287 | * | ||
1288 | * Allocates a new remote processor handle, but does not register | ||
1289 | * it yet. | ||
1290 | * | ||
1291 | * This function should be used by rproc implementations during initialization | ||
1292 | * of the remote processor. | ||
1293 | * | ||
1294 | * After creating an rproc handle using this function, and when ready, | ||
1295 | * implementations should then call rproc_register() to complete | ||
1296 | * the registration of the remote processor. | ||
1297 | * | ||
1298 | * On success the new rproc is returned, and on failure, NULL. | ||
1299 | * | ||
1300 | * Note: _never_ directly deallocate @rproc, even if it was not registered | ||
1301 | * yet. Instead, if you just need to unroll rproc_alloc(), use rproc_free(). | ||
1302 | */ | ||
1303 | struct rproc *rproc_alloc(struct device *dev, const char *name, | ||
1304 | const struct rproc_ops *ops, | ||
1305 | const char *firmware, int len) | ||
1306 | { | ||
1307 | struct rproc *rproc; | ||
1308 | |||
1309 | if (!dev || !name || !ops) | ||
1310 | return NULL; | ||
1311 | |||
1312 | rproc = kzalloc(sizeof(struct rproc) + len, GFP_KERNEL); | ||
1313 | if (!rproc) { | ||
1314 | dev_err(dev, "%s: kzalloc failed\n", __func__); | ||
1315 | return NULL; | ||
1316 | } | ||
1317 | |||
1318 | rproc->dev = dev; | ||
1319 | rproc->name = name; | ||
1320 | rproc->ops = ops; | ||
1321 | rproc->firmware = firmware; | ||
1322 | rproc->priv = &rproc[1]; | ||
1323 | |||
1324 | atomic_set(&rproc->power, 0); | ||
1325 | |||
1326 | kref_init(&rproc->refcount); | ||
1327 | |||
1328 | mutex_init(&rproc->lock); | ||
1329 | |||
1330 | INIT_LIST_HEAD(&rproc->carveouts); | ||
1331 | INIT_LIST_HEAD(&rproc->mappings); | ||
1332 | INIT_LIST_HEAD(&rproc->traces); | ||
1333 | |||
1334 | rproc->state = RPROC_OFFLINE; | ||
1335 | |||
1336 | return rproc; | ||
1337 | } | ||
1338 | EXPORT_SYMBOL(rproc_alloc); | ||
1339 | |||
1340 | /** | ||
1341 | * rproc_free() - free an rproc handle that was allocated by rproc_alloc | ||
1342 | * @rproc: the remote processor handle | ||
1343 | * | ||
1344 | * This function should _only_ be used if @rproc was only allocated, | ||
1345 | * but not registered yet. | ||
1346 | * | ||
1347 | * If @rproc was already successfully registered (by calling rproc_register()), | ||
1348 | * then use rproc_unregister() instead. | ||
1349 | */ | ||
1350 | void rproc_free(struct rproc *rproc) | ||
1351 | { | ||
1352 | kfree(rproc); | ||
1353 | } | ||
1354 | EXPORT_SYMBOL(rproc_free); | ||
1355 | |||
1356 | /** | ||
1357 | * rproc_unregister() - unregister a remote processor | ||
1358 | * @rproc: rproc handle to unregister | ||
1359 | * | ||
1360 | * Unregisters a remote processor, and decrements its refcount. | ||
1361 | * If its refcount drops to zero, then @rproc will be freed. If not, | ||
1362 | * it will be freed later once the last reference is dropped. | ||
1363 | * | ||
1364 | * This function should be called when the platform specific rproc | ||
1365 | * implementation decides to remove the rproc device. it should | ||
1366 | * _only_ be called if a previous invocation of rproc_register() | ||
1367 | * has completed successfully. | ||
1368 | * | ||
1369 | * After rproc_unregister() returns, @rproc is _not_ valid anymore and | ||
1370 | * it shouldn't be used. More specifically, don't call rproc_free() | ||
1371 | * or try to directly free @rproc after rproc_unregister() returns; | ||
1372 | * none of these are needed, and calling them is a bug. | ||
1373 | * | ||
1374 | * Returns 0 on success and -EINVAL if @rproc isn't valid. | ||
1375 | */ | ||
1376 | int rproc_unregister(struct rproc *rproc) | ||
1377 | { | ||
1378 | if (!rproc) | ||
1379 | return -EINVAL; | ||
1380 | |||
1381 | /* if rproc is just being registered, wait */ | ||
1382 | wait_for_completion(&rproc->firmware_loading_complete); | ||
1383 | |||
1384 | /* was an rpmsg vdev created ? */ | ||
1385 | if (rproc->rvdev) | ||
1386 | rproc_remove_rpmsg_vdev(rproc); | ||
1387 | |||
1388 | klist_remove(&rproc->node); | ||
1389 | |||
1390 | kref_put(&rproc->refcount, rproc_release); | ||
1391 | |||
1392 | return 0; | ||
1393 | } | ||
1394 | EXPORT_SYMBOL(rproc_unregister); | ||
1395 | |||
1396 | static int __init remoteproc_init(void) | ||
1397 | { | ||
1398 | rproc_init_debugfs(); | ||
1399 | return 0; | ||
1400 | } | ||
1401 | module_init(remoteproc_init); | ||
1402 | |||
1403 | static void __exit remoteproc_exit(void) | ||
1404 | { | ||
1405 | rproc_exit_debugfs(); | ||
1406 | } | ||
1407 | module_exit(remoteproc_exit); | ||
1408 | |||
1409 | MODULE_LICENSE("GPL v2"); | ||
1410 | MODULE_DESCRIPTION("Generic Remote Processor Framework"); | ||
diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h new file mode 100644 index 000000000000..8b2fc40e92d0 --- /dev/null +++ b/drivers/remoteproc/remoteproc_internal.h | |||
@@ -0,0 +1,44 @@ | |||
1 | /* | ||
2 | * Remote processor framework | ||
3 | * | ||
4 | * Copyright (C) 2011 Texas Instruments, Inc. | ||
5 | * Copyright (C) 2011 Google, Inc. | ||
6 | * | ||
7 | * Ohad Ben-Cohen <ohad@wizery.com> | ||
8 | * Brian Swetland <swetland@google.com> | ||
9 | * | ||
10 | * This software is licensed under the terms of the GNU General Public | ||
11 | * License version 2, as published by the Free Software Foundation, and | ||
12 | * may be copied, distributed, and modified under those terms. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | */ | ||
19 | |||
20 | #ifndef REMOTEPROC_INTERNAL_H | ||
21 | #define REMOTEPROC_INTERNAL_H | ||
22 | |||
23 | #include <linux/irqreturn.h> | ||
24 | |||
25 | struct rproc; | ||
26 | |||
27 | /* from remoteproc_core.c */ | ||
28 | void rproc_release(struct kref *kref); | ||
29 | irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int vq_id); | ||
30 | |||
31 | /* from remoteproc_rpmsg.c */ | ||
32 | int rproc_add_rpmsg_vdev(struct rproc *); | ||
33 | void rproc_remove_rpmsg_vdev(struct rproc *rproc); | ||
34 | |||
35 | /* from remoteproc_debugfs.c */ | ||
36 | void rproc_remove_trace_file(struct dentry *tfile); | ||
37 | struct dentry *rproc_create_trace_file(const char *name, struct rproc *rproc, | ||
38 | struct rproc_mem_entry *trace); | ||
39 | void rproc_delete_debug_dir(struct rproc *rproc); | ||
40 | void rproc_create_debug_dir(struct rproc *rproc); | ||
41 | void rproc_init_debugfs(void); | ||
42 | void rproc_exit_debugfs(void); | ||
43 | |||
44 | #endif /* REMOTEPROC_INTERNAL_H */ | ||
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h new file mode 100644 index 000000000000..1edbfde4593c --- /dev/null +++ b/include/linux/remoteproc.h | |||
@@ -0,0 +1,265 @@ | |||
1 | /* | ||
2 | * Remote Processor Framework | ||
3 | * | ||
4 | * Copyright(c) 2011 Texas Instruments, Inc. | ||
5 | * Copyright(c) 2011 Google, Inc. | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions | ||
10 | * are met: | ||
11 | * | ||
12 | * * Redistributions of source code must retain the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer. | ||
14 | * * Redistributions in binary form must reproduce the above copyright | ||
15 | * notice, this list of conditions and the following disclaimer in | ||
16 | * the documentation and/or other materials provided with the | ||
17 | * distribution. | ||
18 | * * Neither the name Texas Instruments nor the names of its | ||
19 | * contributors may be used to endorse or promote products derived | ||
20 | * from this software without specific prior written permission. | ||
21 | * | ||
22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
23 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
24 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
25 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
26 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
27 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
28 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
29 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
32 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
33 | */ | ||
34 | |||
35 | #ifndef REMOTEPROC_H | ||
36 | #define REMOTEPROC_H | ||
37 | |||
38 | #include <linux/types.h> | ||
39 | #include <linux/kref.h> | ||
40 | #include <linux/klist.h> | ||
41 | #include <linux/mutex.h> | ||
42 | #include <linux/virtio.h> | ||
43 | #include <linux/completion.h> | ||
44 | |||
45 | /* | ||
46 | * The alignment between the consumer and producer parts of the vring. | ||
47 | * Note: this is part of the "wire" protocol. If you change this, you need | ||
48 | * to update your peers too. | ||
49 | */ | ||
50 | #define AMP_VRING_ALIGN (4096) | ||
51 | |||
52 | /** | ||
53 | * struct fw_resource - describes an entry from the resource section | ||
54 | * @type: resource type | ||
55 | * @id: index number of the resource | ||
56 | * @da: device address of the resource | ||
57 | * @pa: physical address of the resource | ||
58 | * @len: size, in bytes, of the resource | ||
59 | * @flags: properties of the resource, e.g. iommu protection required | ||
60 | * @reserved: must be 0 atm | ||
61 | * @name: name of resource | ||
62 | * | ||
63 | * The remote processor firmware should contain a "resource table": | ||
64 | * array of 'struct fw_resource' entries. | ||
65 | * | ||
66 | * Some resources entries are mere announcements, where the host is informed | ||
67 | * of specific remoteproc configuration. Other entries require the host to | ||
68 | * do something (e.g. reserve a requested resource) and possibly also reply | ||
69 | * by overwriting a member inside 'struct fw_resource' with info about the | ||
70 | * allocated resource. | ||
71 | * | ||
72 | * Different resource entries use different members of this struct, | ||
73 | * with different meanings. This is pretty limiting and error-prone, | ||
74 | * so the plan is to move to variable-length TLV-based resource entries, | ||
75 | * where each resource type will have its own structure. | ||
76 | */ | ||
77 | struct fw_resource { | ||
78 | u32 type; | ||
79 | u32 id; | ||
80 | u64 da; | ||
81 | u64 pa; | ||
82 | u32 len; | ||
83 | u32 flags; | ||
84 | u8 reserved[16]; | ||
85 | u8 name[48]; | ||
86 | } __packed; | ||
87 | |||
88 | /** | ||
89 | * enum fw_resource_type - types of resource entries | ||
90 | * | ||
91 | * @RSC_CARVEOUT: request for allocation of a physically contiguous | ||
92 | * memory region. | ||
93 | * @RSC_DEVMEM: request to iommu_map a memory-based peripheral. | ||
94 | * @RSC_TRACE: announces the availability of a trace buffer into which | ||
95 | * the remote processor will be writing logs. In this case, | ||
96 | * 'da' indicates the device address where logs are written to, | ||
97 | * and 'len' is the size of the trace buffer. | ||
98 | * @RSC_VRING: request for allocation of a virtio vring (address should | ||
99 | * be indicated in 'da', and 'len' should contain the number | ||
100 | * of buffers supported by the vring). | ||
101 | * @RSC_VIRTIO_DEV: this entry declares about support for a virtio device, | ||
102 | * and serves as the virtio header. 'da' holds the | ||
103 | * the virtio device features, 'pa' holds the virtio guest | ||
104 | * features, 'len' holds the virtio status, and 'flags' holds | ||
105 | * the virtio id (currently only VIRTIO_ID_RPMSG is supported). | ||
106 | * | ||
107 | * Most of the resource entries share the basic idea of address/length | ||
108 | * negotiation with the host: the firmware usually asks (on behalf of the | ||
109 | * remote processor that will soon be booted with it) for memory | ||
110 | * of size 'len' bytes, and the host needs to allocate it and provide | ||
111 | * the device/physical address (when relevant) in 'da'/'pa' respectively. | ||
112 | * | ||
113 | * If the firmware is compiled with hard coded device addresses, and | ||
114 | * can't handle dynamically allocated 'da' values, then the 'da' field | ||
115 | * will contain the expected device addresses (today we actually only support | ||
116 | * this scheme, as there aren't yet any use cases for dynamically allocated | ||
117 | * device addresses). | ||
118 | */ | ||
119 | enum fw_resource_type { | ||
120 | RSC_CARVEOUT = 0, | ||
121 | RSC_DEVMEM = 1, | ||
122 | RSC_TRACE = 2, | ||
123 | RSC_VRING = 3, | ||
124 | RSC_VIRTIO_DEV = 4, | ||
125 | RSC_VIRTIO_CFG = 5, | ||
126 | }; | ||
127 | |||
128 | /** | ||
129 | * struct rproc_mem_entry - memory entry descriptor | ||
130 | * @va: virtual address | ||
131 | * @dma: dma address | ||
132 | * @len: length, in bytes | ||
133 | * @da: device address | ||
134 | * @priv: associated data | ||
135 | * @node: list node | ||
136 | */ | ||
137 | struct rproc_mem_entry { | ||
138 | void *va; | ||
139 | dma_addr_t dma; | ||
140 | int len; | ||
141 | u64 da; | ||
142 | void *priv; | ||
143 | struct list_head node; | ||
144 | }; | ||
145 | |||
146 | struct rproc; | ||
147 | |||
148 | /** | ||
149 | * struct rproc_ops - platform-specific device handlers | ||
150 | * @start: power on the device and boot it | ||
151 | * @stop: power off the device | ||
152 | * @kick: kick a virtqueue (virtqueue id given as a parameter) | ||
153 | */ | ||
154 | struct rproc_ops { | ||
155 | int (*start)(struct rproc *rproc); | ||
156 | int (*stop)(struct rproc *rproc); | ||
157 | void (*kick)(struct rproc *rproc, int vqid); | ||
158 | }; | ||
159 | |||
160 | /** | ||
161 | * enum rproc_state - remote processor states | ||
162 | * @RPROC_OFFLINE: device is powered off | ||
163 | * @RPROC_SUSPENDED: device is suspended; needs to be woken up to receive | ||
164 | * a message. | ||
165 | * @RPROC_RUNNING: device is up and running | ||
166 | * @RPROC_CRASHED: device has crashed; need to start recovery | ||
167 | * @RPROC_LAST: just keep this one at the end | ||
168 | * | ||
169 | * Please note that the values of these states are used as indices | ||
170 | * to rproc_state_string, a state-to-name lookup table, | ||
171 | * so please keep the two synchronized. @RPROC_LAST is used to check | ||
172 | * the validity of an index before the lookup table is accessed, so | ||
173 | * please update it as needed too. | ||
174 | */ | ||
175 | enum rproc_state { | ||
176 | RPROC_OFFLINE = 0, | ||
177 | RPROC_SUSPENDED = 1, | ||
178 | RPROC_RUNNING = 2, | ||
179 | RPROC_CRASHED = 3, | ||
180 | RPROC_LAST = 4, | ||
181 | }; | ||
182 | |||
183 | /** | ||
184 | * struct rproc - represents a physical remote processor device | ||
185 | * @node: klist node of this rproc object | ||
186 | * @domain: iommu domain | ||
187 | * @name: human readable name of the rproc | ||
188 | * @firmware: name of firmware file to be loaded | ||
189 | * @priv: private data which belongs to the platform-specific rproc module | ||
190 | * @ops: platform-specific start/stop rproc handlers | ||
191 | * @dev: underlying device | ||
192 | * @refcount: refcount of users that have a valid pointer to this rproc | ||
193 | * @power: refcount of users who need this rproc powered up | ||
194 | * @state: state of the device | ||
195 | * @lock: lock which protects concurrent manipulations of the rproc | ||
196 | * @dbg_dir: debugfs directory of this rproc device | ||
197 | * @traces: list of trace buffers | ||
198 | * @num_traces: number of trace buffers | ||
199 | * @carveouts: list of physically contiguous memory allocations | ||
200 | * @mappings: list of iommu mappings we initiated, needed on shutdown | ||
201 | * @firmware_loading_complete: marks e/o asynchronous firmware loading | ||
202 | * @bootaddr: address of first instruction to boot rproc with (optional) | ||
203 | * @rvdev: virtio device (we only support a single rpmsg virtio device for now) | ||
204 | */ | ||
205 | struct rproc { | ||
206 | struct klist_node node; | ||
207 | struct iommu_domain *domain; | ||
208 | const char *name; | ||
209 | const char *firmware; | ||
210 | void *priv; | ||
211 | const struct rproc_ops *ops; | ||
212 | struct device *dev; | ||
213 | struct kref refcount; | ||
214 | atomic_t power; | ||
215 | unsigned int state; | ||
216 | struct mutex lock; | ||
217 | struct dentry *dbg_dir; | ||
218 | struct list_head traces; | ||
219 | int num_traces; | ||
220 | struct list_head carveouts; | ||
221 | struct list_head mappings; | ||
222 | struct completion firmware_loading_complete; | ||
223 | u64 bootaddr; | ||
224 | struct rproc_vdev *rvdev; | ||
225 | }; | ||
226 | |||
227 | /** | ||
228 | * struct rproc_vdev - remoteproc state for a supported virtio device | ||
229 | * @rproc: the rproc handle | ||
230 | * @vdev: the virio device | ||
231 | * @vq: the virtqueues for this vdev | ||
232 | * @vring: the vrings for this vdev | ||
233 | * @dfeatures: virtio device features | ||
234 | * @gfeatures: virtio guest features | ||
235 | */ | ||
236 | struct rproc_vdev { | ||
237 | struct rproc *rproc; | ||
238 | struct virtio_device vdev; | ||
239 | struct virtqueue *vq[2]; | ||
240 | struct rproc_mem_entry vring[2]; | ||
241 | unsigned long dfeatures; | ||
242 | unsigned long gfeatures; | ||
243 | }; | ||
244 | |||
245 | struct rproc *rproc_get_by_name(const char *name); | ||
246 | void rproc_put(struct rproc *rproc); | ||
247 | |||
248 | struct rproc *rproc_alloc(struct device *dev, const char *name, | ||
249 | const struct rproc_ops *ops, | ||
250 | const char *firmware, int len); | ||
251 | void rproc_free(struct rproc *rproc); | ||
252 | int rproc_register(struct rproc *rproc); | ||
253 | int rproc_unregister(struct rproc *rproc); | ||
254 | |||
255 | int rproc_boot(struct rproc *rproc); | ||
256 | void rproc_shutdown(struct rproc *rproc); | ||
257 | |||
258 | static inline struct rproc *vdev_to_rproc(struct virtio_device *vdev) | ||
259 | { | ||
260 | struct rproc_vdev *rvdev = container_of(vdev, struct rproc_vdev, vdev); | ||
261 | |||
262 | return rvdev->rproc; | ||
263 | } | ||
264 | |||
265 | #endif /* REMOTEPROC_H */ | ||