diff options
-rw-r--r-- | Documentation/remoteproc.txt | 136 | ||||
-rw-r--r-- | drivers/remoteproc/Kconfig | 3 | ||||
-rw-r--r-- | drivers/remoteproc/Makefile | 2 | ||||
-rw-r--r-- | drivers/remoteproc/omap_remoteproc.c | 11 | ||||
-rw-r--r-- | drivers/remoteproc/remoteproc_core.c | 532 | ||||
-rw-r--r-- | drivers/remoteproc/remoteproc_internal.h | 6 | ||||
-rw-r--r-- | drivers/remoteproc/remoteproc_virtio.c (renamed from drivers/remoteproc/remoteproc_rpmsg.c) | 162 | ||||
-rw-r--r-- | drivers/rpmsg/virtio_rpmsg_bus.c | 46 | ||||
-rw-r--r-- | include/linux/remoteproc.h | 339 |
9 files changed, 793 insertions, 444 deletions
diff --git a/Documentation/remoteproc.txt b/Documentation/remoteproc.txt index 23ff7349ffe7..70a048cd3fa3 100644 --- a/Documentation/remoteproc.txt +++ b/Documentation/remoteproc.txt | |||
@@ -20,6 +20,11 @@ platform-specific remoteproc drivers only need to provide a few low-level | |||
20 | handlers, and then all rpmsg drivers will then just work | 20 | handlers, and then all rpmsg drivers will then just work |
21 | (for more information about the virtio-based rpmsg bus and its drivers, | 21 | (for more information about the virtio-based rpmsg bus and its drivers, |
22 | please read Documentation/rpmsg.txt). | 22 | please read Documentation/rpmsg.txt). |
23 | Registration of other types of virtio devices is now also possible. Firmwares | ||
24 | just need to publish what kind of virtio devices do they support, and then | ||
25 | remoteproc will add those devices. This makes it possible to reuse the | ||
26 | existing virtio drivers with remote processor backends at a minimal development | ||
27 | cost. | ||
23 | 28 | ||
24 | 2. User API | 29 | 2. User API |
25 | 30 | ||
@@ -136,8 +141,6 @@ int dummy_rproc_example(struct rproc *my_rproc) | |||
136 | If found, those virtio devices will be created and added, so as a result | 141 | 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 | 142 | of registering this remote processor, additional virtio drivers might get |
138 | probed. | 143 | probed. |
139 | Currently, though, we only support a single RPMSG virtio vdev per remote | ||
140 | processor. | ||
141 | 144 | ||
142 | int rproc_unregister(struct rproc *rproc) | 145 | int rproc_unregister(struct rproc *rproc) |
143 | - Unregister a remote processor, and decrement its refcount. | 146 | - Unregister a remote processor, and decrement its refcount. |
@@ -174,7 +177,7 @@ struct rproc_ops { | |||
174 | }; | 177 | }; |
175 | 178 | ||
176 | Every remoteproc implementation should at least provide the ->start and ->stop | 179 | Every remoteproc implementation should at least provide the ->start and ->stop |
177 | handlers. If rpmsg functionality is also desired, then the ->kick handler | 180 | handlers. If rpmsg/virtio functionality is also desired, then the ->kick handler |
178 | should be provided as well. | 181 | should be provided as well. |
179 | 182 | ||
180 | The ->start() handler takes an rproc handle and should then power on the | 183 | The ->start() handler takes an rproc handle and should then power on the |
@@ -221,43 +224,52 @@ resource entries that publish the existence of supported features | |||
221 | or configurations by the remote processor, such as trace buffers and | 224 | or configurations by the remote processor, such as trace buffers and |
222 | supported virtio devices (and their configurations). | 225 | supported virtio devices (and their configurations). |
223 | 226 | ||
224 | Currently the resource table is just an array of: | 227 | The resource table begins with this header: |
225 | 228 | ||
226 | /** | 229 | /** |
227 | * struct fw_resource - describes an entry from the resource section | 230 | * struct resource_table - firmware resource table header |
231 | * @ver: version number | ||
232 | * @num: number of resource entries | ||
233 | * @reserved: reserved (must be zero) | ||
234 | * @offset: array of offsets pointing at the various resource entries | ||
235 | * | ||
236 | * The header of the resource table, as expressed by this structure, | ||
237 | * contains a version number (should we need to change this format in the | ||
238 | * future), the number of available resource entries, and their offsets | ||
239 | * in the table. | ||
240 | */ | ||
241 | struct resource_table { | ||
242 | u32 ver; | ||
243 | u32 num; | ||
244 | u32 reserved[2]; | ||
245 | u32 offset[0]; | ||
246 | } __packed; | ||
247 | |||
248 | Immediately following this header are the resource entries themselves, | ||
249 | each of which begins with the following resource entry header: | ||
250 | |||
251 | /** | ||
252 | * struct fw_rsc_hdr - firmware resource entry header | ||
228 | * @type: resource type | 253 | * @type: resource type |
229 | * @id: index number of the resource | 254 | * @data: resource data |
230 | * @da: device address of the resource | 255 | * |
231 | * @pa: physical address of the resource | 256 | * Every resource entry begins with a 'struct fw_rsc_hdr' header providing |
232 | * @len: size, in bytes, of the resource | 257 | * its @type. The content of the entry itself will immediately follow |
233 | * @flags: properties of the resource, e.g. iommu protection required | 258 | * this header, and it should be parsed according to the resource type. |
234 | * @reserved: must be 0 atm | ||
235 | * @name: name of resource | ||
236 | */ | 259 | */ |
237 | struct fw_resource { | 260 | struct fw_rsc_hdr { |
238 | u32 type; | 261 | u32 type; |
239 | u32 id; | 262 | u8 data[0]; |
240 | u64 da; | ||
241 | u64 pa; | ||
242 | u32 len; | ||
243 | u32 flags; | ||
244 | u8 reserved[16]; | ||
245 | u8 name[48]; | ||
246 | } __packed; | 263 | } __packed; |
247 | 264 | ||
248 | Some resources entries are mere announcements, where the host is informed | 265 | Some resources entries are mere announcements, where the host is informed |
249 | of specific remoteproc configuration. Other entries require the host to | 266 | of specific remoteproc configuration. Other entries require the host to |
250 | do something (e.g. reserve a requested resource) and possibly also reply | 267 | do something (e.g. allocate a system resource). Sometimes a negotiation |
251 | by overwriting a member inside 'struct fw_resource' with info about the | 268 | is expected, where the firmware requests a resource, and once allocated, |
252 | allocated resource. | 269 | the host should provide back its details (e.g. address of an allocated |
253 | 270 | memory region). | |
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 | 271 | ||
260 | Here are the resource types that are currently being used: | 272 | Here are the various resource types that are currently supported: |
261 | 273 | ||
262 | /** | 274 | /** |
263 | * enum fw_resource_type - types of resource entries | 275 | * enum fw_resource_type - types of resource entries |
@@ -266,59 +278,45 @@ Here are the resource types that are currently being used: | |||
266 | * memory region. | 278 | * memory region. |
267 | * @RSC_DEVMEM: request to iommu_map a memory-based peripheral. | 279 | * @RSC_DEVMEM: request to iommu_map a memory-based peripheral. |
268 | * @RSC_TRACE: announces the availability of a trace buffer into which | 280 | * @RSC_TRACE: announces the availability of a trace buffer into which |
269 | * the remote processor will be writing logs. In this case, | 281 | * the remote processor will be writing logs. |
270 | * 'da' indicates the device address where logs are written to, | 282 | * @RSC_VDEV: declare support for a virtio device, and serve as its |
271 | * and 'len' is the size of the trace buffer. | 283 | * virtio header. |
272 | * @RSC_VRING: request for allocation of a virtio vring (address should | 284 | * @RSC_LAST: just keep this one at the end |
273 | * be indicated in 'da', and 'len' should contain the number | 285 | * |
274 | * of buffers supported by the vring). | 286 | * Please note that these values are used as indices to the rproc_handle_rsc |
275 | * @RSC_VIRTIO_DEV: announces support for a virtio device, and serves as | 287 | * lookup table, so please keep them sane. Moreover, @RSC_LAST is used to |
276 | * the virtio header. 'da' contains the virtio device | 288 | * check the validity of an index before the lookup table is accessed, so |
277 | * features, 'pa' holds the virtio guest features (host | 289 | * please update it as needed. |
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 | */ | 290 | */ |
282 | enum fw_resource_type { | 291 | enum fw_resource_type { |
283 | RSC_CARVEOUT = 0, | 292 | RSC_CARVEOUT = 0, |
284 | RSC_DEVMEM = 1, | 293 | RSC_DEVMEM = 1, |
285 | RSC_TRACE = 2, | 294 | RSC_TRACE = 2, |
286 | RSC_VRING = 3, | 295 | RSC_VDEV = 3, |
287 | RSC_VIRTIO_DEV = 4, | 296 | RSC_LAST = 4, |
288 | RSC_VIRTIO_CFG = 5, | ||
289 | }; | 297 | }; |
290 | 298 | ||
291 | Most of the resource entries share the basic idea of address/length | 299 | For more details regarding a specific resource type, please see its |
292 | negotiation with the host: the firmware usually asks for memory | 300 | dedicated structure in include/linux/remoteproc.h. |
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 | 301 | ||
302 | We also expect that platform-specific resource entries will show up | 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 | 303 | at some point. When that happens, we could easily add a new RSC_PLATFORM |
304 | type, and hand those resources to the platform-specific rproc driver to handle. | 304 | type, and hand those resources to the platform-specific rproc driver to handle. |
305 | 305 | ||
306 | 7. Virtio and remoteproc | 306 | 7. Virtio and remoteproc |
307 | 307 | ||
308 | The firmware should provide remoteproc information about virtio devices | 308 | The firmware should provide remoteproc information about virtio devices |
309 | that it supports, and their configurations: a RSC_VIRTIO_DEV resource entry | 309 | that it supports, and their configurations: a RSC_VDEV resource entry |
310 | should specify the virtio device id, and subsequent RSC_VRING resource entries | 310 | should specify the virtio device id (as in virtio_ids.h), virtio features, |
311 | should indicate the vring size (i.e. how many buffers do they support) and | 311 | virtio config space, vrings information, etc. |
312 | where should they be mapped (i.e. which device address). Note: the alignment | 312 | |
313 | between the consumer and producer parts of the vring is assumed to be 4096. | 313 | When a new remote processor is registered, the remoteproc framework |
314 | 314 | will look for its resource table and will register the virtio devices | |
315 | At this point we only support a single virtio rpmsg device per remote | 315 | it supports. A firmware may support any number of virtio devices, and |
316 | processor, but the plan is to remove this limitation. In addition, once we | 316 | of any type (a single remote processor can also easily support several |
317 | move to TLV-based resource table, the plan is to have a single RSC_VIRTIO | 317 | rpmsg virtio devices this way, if desired). |
318 | entry per supported virtio device, which will include the virtio header, | 318 | |
319 | the vrings information and the virtio config space. | 319 | Of course, RSC_VDEV resource entries are only good enough for static |
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 | 320 | 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 | 321 | using the rpmsg bus (similar to how we already do dynamic allocations of |
324 | rpmsg channels; read more about it in rpmsg.txt). | 322 | rpmsg channels; read more about it in rpmsg.txt). |
diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index 25fc4ccbc2ea..24d880e78ec6 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig | |||
@@ -8,11 +8,10 @@ config REMOTEPROC | |||
8 | config OMAP_REMOTEPROC | 8 | config OMAP_REMOTEPROC |
9 | tristate "OMAP remoteproc support" | 9 | tristate "OMAP remoteproc support" |
10 | depends on ARCH_OMAP4 | 10 | depends on ARCH_OMAP4 |
11 | select OMAP_IOMMU | 11 | depends on OMAP_IOMMU |
12 | select REMOTEPROC | 12 | select REMOTEPROC |
13 | select OMAP_MBOX_FWK | 13 | select OMAP_MBOX_FWK |
14 | select RPMSG | 14 | select RPMSG |
15 | default m | ||
16 | help | 15 | help |
17 | Say y here to support OMAP's remote processors (dual M3 | 16 | Say y here to support OMAP's remote processors (dual M3 |
18 | and DSP on OMAP4) via the remote processor framework. | 17 | and DSP on OMAP4) via the remote processor framework. |
diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile index df0897f69e16..5445d9b23294 100644 --- a/drivers/remoteproc/Makefile +++ b/drivers/remoteproc/Makefile | |||
@@ -5,5 +5,5 @@ | |||
5 | obj-$(CONFIG_REMOTEPROC) += remoteproc.o | 5 | obj-$(CONFIG_REMOTEPROC) += remoteproc.o |
6 | remoteproc-y := remoteproc_core.o | 6 | remoteproc-y := remoteproc_core.o |
7 | remoteproc-y += remoteproc_debugfs.o | 7 | remoteproc-y += remoteproc_debugfs.o |
8 | remoteproc-y += remoteproc_rpmsg.o | 8 | remoteproc-y += remoteproc_virtio.o |
9 | obj-$(CONFIG_OMAP_REMOTEPROC) += omap_remoteproc.o | 9 | obj-$(CONFIG_OMAP_REMOTEPROC) += omap_remoteproc.o |
diff --git a/drivers/remoteproc/omap_remoteproc.c b/drivers/remoteproc/omap_remoteproc.c index aa3ce52dc65e..69425c4e86f3 100644 --- a/drivers/remoteproc/omap_remoteproc.c +++ b/drivers/remoteproc/omap_remoteproc.c | |||
@@ -80,16 +80,7 @@ static int omap_rproc_mbox_callback(struct notifier_block *this, | |||
80 | dev_info(dev, "received echo reply from %s\n", name); | 80 | dev_info(dev, "received echo reply from %s\n", name); |
81 | break; | 81 | break; |
82 | default: | 82 | default: |
83 | /* ignore vq indices which are too large to be valid */ | 83 | /* msg contains the index of the triggered vring */ |
84 | if (msg >= 2) { | ||
85 | dev_warn(dev, "invalid mbox msg: 0x%x\n", msg); | ||
86 | break; | ||
87 | } | ||
88 | |||
89 | /* | ||
90 | * At this point, 'msg' contains the index of the vring | ||
91 | * which was just triggered. | ||
92 | */ | ||
93 | if (rproc_vq_interrupt(oproc->rproc, msg) == IRQ_NONE) | 84 | if (rproc_vq_interrupt(oproc->rproc, msg) == IRQ_NONE) |
94 | dev_dbg(dev, "no message was found in vqid %d\n", msg); | 85 | dev_dbg(dev, "no message was found in vqid %d\n", msg); |
95 | } | 86 | } |
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index 729911b67a9a..ee15c68fb519 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c | |||
@@ -52,8 +52,8 @@ static void klist_rproc_put(struct klist_node *n); | |||
52 | * We need this in order to support name-based lookups (needed by the | 52 | * We need this in order to support name-based lookups (needed by the |
53 | * rproc_get_by_name()). | 53 | * rproc_get_by_name()). |
54 | * | 54 | * |
55 | * That said, we don't use rproc_get_by_name() anymore within the rpmsg | 55 | * That said, we don't use rproc_get_by_name() at this point. |
56 | * framework. The use cases that do require its existence should be | 56 | * The use cases that do require its existence should be |
57 | * scrutinized, and hopefully migrated to rproc_boot() using device-based | 57 | * scrutinized, and hopefully migrated to rproc_boot() using device-based |
58 | * binding. | 58 | * binding. |
59 | * | 59 | * |
@@ -63,9 +63,8 @@ static void klist_rproc_put(struct klist_node *n); | |||
63 | static DEFINE_KLIST(rprocs, klist_rproc_get, klist_rproc_put); | 63 | static DEFINE_KLIST(rprocs, klist_rproc_get, klist_rproc_put); |
64 | 64 | ||
65 | typedef int (*rproc_handle_resources_t)(struct rproc *rproc, | 65 | typedef int (*rproc_handle_resources_t)(struct rproc *rproc, |
66 | struct fw_resource *rsc, int len); | 66 | struct resource_table *table, int len); |
67 | typedef int (*rproc_handle_resource_t)(struct rproc *rproc, | 67 | typedef int (*rproc_handle_resource_t)(struct rproc *rproc, void *, int avail); |
68 | struct fw_resource *rsc); | ||
69 | 68 | ||
70 | /* | 69 | /* |
71 | * This is the IOMMU fault handler we register with the IOMMU API | 70 | * This is the IOMMU fault handler we register with the IOMMU API |
@@ -280,145 +279,182 @@ rproc_load_segments(struct rproc *rproc, const u8 *elf_data, size_t len) | |||
280 | return ret; | 279 | return ret; |
281 | } | 280 | } |
282 | 281 | ||
283 | /** | 282 | static int |
284 | * rproc_handle_virtio_hdr() - handle a virtio header resource | 283 | __rproc_handle_vring(struct rproc_vdev *rvdev, struct fw_rsc_vdev *rsc, int i) |
285 | * @rproc: the remote processor | ||
286 | * @rsc: the resource descriptor | ||
287 | * | ||
288 | * The existence of this virtio hdr resource entry means that the firmware | ||
289 | * of this @rproc supports this virtio device. | ||
290 | * | ||
291 | * Currently we support only a single virtio device of type VIRTIO_ID_RPMSG, | ||
292 | * but the plan is to remove this limitation and support any number | ||
293 | * of virtio devices (and of any type). We'll also add support for dynamically | ||
294 | * adding (and removing) virtio devices over the rpmsg bus, but small | ||
295 | * firmwares that doesn't want to get involved with rpmsg will be able | ||
296 | * to simple use the resource table for this. | ||
297 | * | ||
298 | * At this point this virtio header entry is rather simple: it just | ||
299 | * announces the virtio device id and the supported virtio device features. | ||
300 | * The plan though is to extend this to include the vring information and | ||
301 | * the virtio config space, too (but first, some resource table overhaul | ||
302 | * is needed: move from fixed-sized to variable-length TLV entries). | ||
303 | * | ||
304 | * For now, the 'flags' member of the resource entry contains the virtio | ||
305 | * device id, the 'da' member contains the device features, and 'pa' is | ||
306 | * where we need to store the guest features once negotiation completes. | ||
307 | * As usual, the 'id' member of this resource contains the index of this | ||
308 | * resource type (i.e. is this the first virtio hdr entry, the 2nd, ...). | ||
309 | * | ||
310 | * Returns 0 on success, or an appropriate error code otherwise | ||
311 | */ | ||
312 | static int rproc_handle_virtio_hdr(struct rproc *rproc, struct fw_resource *rsc) | ||
313 | { | 284 | { |
314 | struct rproc_vdev *rvdev; | 285 | struct rproc *rproc = rvdev->rproc; |
286 | struct device *dev = rproc->dev; | ||
287 | struct fw_rsc_vdev_vring *vring = &rsc->vring[i]; | ||
288 | dma_addr_t dma; | ||
289 | void *va; | ||
290 | int ret, size, notifyid; | ||
291 | |||
292 | dev_dbg(dev, "vdev rsc: vring%d: da %x, qsz %d, align %d\n", | ||
293 | i, vring->da, vring->num, vring->align); | ||
315 | 294 | ||
316 | /* we only support VIRTIO_ID_RPMSG devices for now */ | 295 | /* make sure reserved bytes are zeroes */ |
317 | if (rsc->flags != VIRTIO_ID_RPMSG) { | 296 | if (vring->reserved) { |
318 | dev_warn(rproc->dev, "unsupported vdev: %d\n", rsc->flags); | 297 | dev_err(dev, "vring rsc has non zero reserved bytes\n"); |
319 | return -EINVAL; | 298 | return -EINVAL; |
320 | } | 299 | } |
321 | 300 | ||
322 | /* we only support a single vdev per rproc for now */ | 301 | /* verify queue size and vring alignment are sane */ |
323 | if (rsc->id || rproc->rvdev) { | 302 | if (!vring->num || !vring->align) { |
324 | dev_warn(rproc->dev, "redundant vdev entry: %s\n", rsc->name); | 303 | dev_err(dev, "invalid qsz (%d) or alignment (%d)\n", |
304 | vring->num, vring->align); | ||
325 | return -EINVAL; | 305 | return -EINVAL; |
326 | } | 306 | } |
327 | 307 | ||
328 | rvdev = kzalloc(sizeof(struct rproc_vdev), GFP_KERNEL); | 308 | /* actual size of vring (in bytes) */ |
329 | if (!rvdev) | 309 | size = PAGE_ALIGN(vring_size(vring->num, vring->align)); |
310 | |||
311 | if (!idr_pre_get(&rproc->notifyids, GFP_KERNEL)) { | ||
312 | dev_err(dev, "idr_pre_get failed\n"); | ||
330 | return -ENOMEM; | 313 | return -ENOMEM; |
314 | } | ||
331 | 315 | ||
332 | /* remember the device features */ | 316 | /* |
333 | rvdev->dfeatures = rsc->da; | 317 | * Allocate non-cacheable memory for the vring. In the future |
318 | * this call will also configure the IOMMU for us | ||
319 | */ | ||
320 | va = dma_alloc_coherent(dev, size, &dma, GFP_KERNEL); | ||
321 | if (!va) { | ||
322 | dev_err(dev, "dma_alloc_coherent failed\n"); | ||
323 | return -EINVAL; | ||
324 | } | ||
334 | 325 | ||
335 | rproc->rvdev = rvdev; | 326 | /* assign an rproc-wide unique index for this vring */ |
336 | rvdev->rproc = rproc; | 327 | /* TODO: assign a notifyid for rvdev updates as well */ |
328 | ret = idr_get_new(&rproc->notifyids, &rvdev->vring[i], ¬ifyid); | ||
329 | if (ret) { | ||
330 | dev_err(dev, "idr_get_new failed: %d\n", ret); | ||
331 | dma_free_coherent(dev, size, va, dma); | ||
332 | return ret; | ||
333 | } | ||
334 | |||
335 | /* let the rproc know the da and notifyid of this vring */ | ||
336 | /* TODO: expose this to remote processor */ | ||
337 | vring->da = dma; | ||
338 | vring->notifyid = notifyid; | ||
339 | |||
340 | dev_dbg(dev, "vring%d: va %p dma %x size %x idr %d\n", i, va, | ||
341 | dma, size, notifyid); | ||
342 | |||
343 | rvdev->vring[i].len = vring->num; | ||
344 | rvdev->vring[i].align = vring->align; | ||
345 | rvdev->vring[i].va = va; | ||
346 | rvdev->vring[i].dma = dma; | ||
347 | rvdev->vring[i].notifyid = notifyid; | ||
348 | rvdev->vring[i].rvdev = rvdev; | ||
337 | 349 | ||
338 | return 0; | 350 | return 0; |
339 | } | 351 | } |
340 | 352 | ||
353 | static void __rproc_free_vrings(struct rproc_vdev *rvdev, int i) | ||
354 | { | ||
355 | struct rproc *rproc = rvdev->rproc; | ||
356 | |||
357 | for (i--; i > 0; i--) { | ||
358 | struct rproc_vring *rvring = &rvdev->vring[i]; | ||
359 | int size = PAGE_ALIGN(vring_size(rvring->len, rvring->align)); | ||
360 | |||
361 | dma_free_coherent(rproc->dev, size, rvring->va, rvring->dma); | ||
362 | idr_remove(&rproc->notifyids, rvring->notifyid); | ||
363 | } | ||
364 | } | ||
365 | |||
341 | /** | 366 | /** |
342 | * rproc_handle_vring() - handle a vring fw resource | 367 | * rproc_handle_vdev() - handle a vdev fw resource |
343 | * @rproc: the remote processor | 368 | * @rproc: the remote processor |
344 | * @rsc: the vring resource descriptor | 369 | * @rsc: the vring resource descriptor |
345 | * | 370 | * @avail: size of available data (for sanity checking the image) |
346 | * This resource entry requires allocation of non-cacheable memory | 371 | * |
347 | * for a virtio vring. Currently we only support two vrings per remote | 372 | * This resource entry requests the host to statically register a virtio |
348 | * processor, required for the virtio rpmsg device. | 373 | * device (vdev), and setup everything needed to support it. It contains |
349 | * | 374 | * everything needed to make it possible: the virtio device id, virtio |
350 | * The 'len' member of @rsc should contain the number of buffers this vring | 375 | * device features, vrings information, virtio config space, etc... |
351 | * support and 'da' should either contain the device address where | 376 | * |
352 | * the remote processor is expecting the vring, or indicate that | 377 | * Before registering the vdev, the vrings are allocated from non-cacheable |
353 | * dynamically allocation of the vring's device address is supported. | 378 | * physically contiguous memory. Currently we only support two vrings per |
354 | * | 379 | * remote processor (temporary limitation). We might also want to consider |
355 | * Note: 'da' is currently not handled. This will be revised when the generic | 380 | * doing the vring allocation only later when ->find_vqs() is invoked, and |
356 | * iommu-based DMA API will arrive, or a dynanic & non-iommu use case show | 381 | * then release them upon ->del_vqs(). |
357 | * up. Meanwhile, statically-addressed iommu-based images should use | 382 | * |
358 | * RSC_DEVMEM resource entries to map their require 'da' to the physical | 383 | * Note: @da is currently not really handled correctly: we dynamically |
359 | * address of their base CMA region. | 384 | * allocate it using the DMA API, ignoring requested hard coded addresses, |
385 | * and we don't take care of any required IOMMU programming. This is all | ||
386 | * going to be taken care of when the generic iommu-based DMA API will be | ||
387 | * merged. Meanwhile, statically-addressed iommu-based firmware images should | ||
388 | * use RSC_DEVMEM resource entries to map their required @da to the physical | ||
389 | * address of their base CMA region (ouch, hacky!). | ||
360 | * | 390 | * |
361 | * Returns 0 on success, or an appropriate error code otherwise | 391 | * Returns 0 on success, or an appropriate error code otherwise |
362 | */ | 392 | */ |
363 | static int rproc_handle_vring(struct rproc *rproc, struct fw_resource *rsc) | 393 | static int rproc_handle_vdev(struct rproc *rproc, struct fw_rsc_vdev *rsc, |
394 | int avail) | ||
364 | { | 395 | { |
365 | struct device *dev = rproc->dev; | 396 | struct device *dev = rproc->dev; |
366 | struct rproc_vdev *rvdev = rproc->rvdev; | 397 | struct rproc_vdev *rvdev; |
367 | dma_addr_t dma; | 398 | int i, ret; |
368 | int size, id = rsc->id; | ||
369 | void *va; | ||
370 | 399 | ||
371 | /* no vdev is in place ? */ | 400 | /* make sure resource isn't truncated */ |
372 | if (!rvdev) { | 401 | if (sizeof(*rsc) + rsc->num_of_vrings * sizeof(struct fw_rsc_vdev_vring) |
373 | dev_err(dev, "vring requested without a virtio dev entry\n"); | 402 | + rsc->config_len > avail) { |
403 | dev_err(rproc->dev, "vdev rsc is truncated\n"); | ||
374 | return -EINVAL; | 404 | return -EINVAL; |
375 | } | 405 | } |
376 | 406 | ||
377 | /* the firmware must provide the expected queue size */ | 407 | /* make sure reserved bytes are zeroes */ |
378 | if (!rsc->len) { | 408 | if (rsc->reserved[0] || rsc->reserved[1]) { |
379 | dev_err(dev, "missing expected queue size\n"); | 409 | dev_err(dev, "vdev rsc has non zero reserved bytes\n"); |
380 | return -EINVAL; | 410 | return -EINVAL; |
381 | } | 411 | } |
382 | 412 | ||
383 | /* we currently support two vrings per rproc (for rx and tx) */ | 413 | dev_dbg(dev, "vdev rsc: id %d, dfeatures %x, cfg len %d, %d vrings\n", |
384 | if (id >= ARRAY_SIZE(rvdev->vring)) { | 414 | rsc->id, rsc->dfeatures, rsc->config_len, rsc->num_of_vrings); |
385 | dev_err(dev, "%s: invalid vring id %d\n", rsc->name, id); | ||
386 | return -EINVAL; | ||
387 | } | ||
388 | 415 | ||
389 | /* have we already allocated this vring id ? */ | 416 | /* we currently support only two vrings per rvdev */ |
390 | if (rvdev->vring[id].len) { | 417 | if (rsc->num_of_vrings > ARRAY_SIZE(rvdev->vring)) { |
391 | dev_err(dev, "%s: duplicated id %d\n", rsc->name, id); | 418 | dev_err(dev, "too many vrings: %d\n", rsc->num_of_vrings); |
392 | return -EINVAL; | 419 | return -EINVAL; |
393 | } | 420 | } |
394 | 421 | ||
395 | /* actual size of vring (in bytes) */ | 422 | rvdev = kzalloc(sizeof(struct rproc_vdev), GFP_KERNEL); |
396 | size = PAGE_ALIGN(vring_size(rsc->len, AMP_VRING_ALIGN)); | 423 | if (!rvdev) |
397 | |||
398 | /* | ||
399 | * Allocate non-cacheable memory for the vring. In the future | ||
400 | * this call will also configure the IOMMU for us | ||
401 | */ | ||
402 | va = dma_alloc_coherent(dev, size, &dma, GFP_KERNEL); | ||
403 | if (!va) { | ||
404 | dev_err(dev, "dma_alloc_coherent failed\n"); | ||
405 | return -ENOMEM; | 424 | return -ENOMEM; |
425 | |||
426 | rvdev->rproc = rproc; | ||
427 | |||
428 | /* allocate the vrings */ | ||
429 | for (i = 0; i < rsc->num_of_vrings; i++) { | ||
430 | ret = __rproc_handle_vring(rvdev, rsc, i); | ||
431 | if (ret) | ||
432 | goto free_vrings; | ||
406 | } | 433 | } |
407 | 434 | ||
408 | dev_dbg(dev, "vring%d: va %p dma %x qsz %d ring size %x\n", id, va, | 435 | /* remember the device features */ |
409 | dma, rsc->len, size); | 436 | rvdev->dfeatures = rsc->dfeatures; |
437 | |||
438 | list_add_tail(&rvdev->node, &rproc->rvdevs); | ||
410 | 439 | ||
411 | rvdev->vring[id].len = rsc->len; | 440 | /* it is now safe to add the virtio device */ |
412 | rvdev->vring[id].va = va; | 441 | ret = rproc_add_virtio_dev(rvdev, rsc->id); |
413 | rvdev->vring[id].dma = dma; | 442 | if (ret) |
443 | goto free_vrings; | ||
414 | 444 | ||
415 | return 0; | 445 | return 0; |
446 | |||
447 | free_vrings: | ||
448 | __rproc_free_vrings(rvdev, i); | ||
449 | kfree(rvdev); | ||
450 | return ret; | ||
416 | } | 451 | } |
417 | 452 | ||
418 | /** | 453 | /** |
419 | * rproc_handle_trace() - handle a shared trace buffer resource | 454 | * rproc_handle_trace() - handle a shared trace buffer resource |
420 | * @rproc: the remote processor | 455 | * @rproc: the remote processor |
421 | * @rsc: the trace resource descriptor | 456 | * @rsc: the trace resource descriptor |
457 | * @avail: size of available data (for sanity checking the image) | ||
422 | * | 458 | * |
423 | * In case the remote processor dumps trace logs into memory, | 459 | * In case the remote processor dumps trace logs into memory, |
424 | * export it via debugfs. | 460 | * export it via debugfs. |
@@ -430,13 +466,25 @@ static int rproc_handle_vring(struct rproc *rproc, struct fw_resource *rsc) | |||
430 | * | 466 | * |
431 | * Returns 0 on success, or an appropriate error code otherwise | 467 | * Returns 0 on success, or an appropriate error code otherwise |
432 | */ | 468 | */ |
433 | static int rproc_handle_trace(struct rproc *rproc, struct fw_resource *rsc) | 469 | static int rproc_handle_trace(struct rproc *rproc, struct fw_rsc_trace *rsc, |
470 | int avail) | ||
434 | { | 471 | { |
435 | struct rproc_mem_entry *trace; | 472 | struct rproc_mem_entry *trace; |
436 | struct device *dev = rproc->dev; | 473 | struct device *dev = rproc->dev; |
437 | void *ptr; | 474 | void *ptr; |
438 | char name[15]; | 475 | char name[15]; |
439 | 476 | ||
477 | if (sizeof(*rsc) > avail) { | ||
478 | dev_err(rproc->dev, "trace rsc is truncated\n"); | ||
479 | return -EINVAL; | ||
480 | } | ||
481 | |||
482 | /* make sure reserved bytes are zeroes */ | ||
483 | if (rsc->reserved) { | ||
484 | dev_err(dev, "trace rsc has non zero reserved bytes\n"); | ||
485 | return -EINVAL; | ||
486 | } | ||
487 | |||
440 | /* what's the kernel address of this resource ? */ | 488 | /* what's the kernel address of this resource ? */ |
441 | ptr = rproc_da_to_va(rproc, rsc->da, rsc->len); | 489 | ptr = rproc_da_to_va(rproc, rsc->da, rsc->len); |
442 | if (!ptr) { | 490 | if (!ptr) { |
@@ -469,7 +517,7 @@ static int rproc_handle_trace(struct rproc *rproc, struct fw_resource *rsc) | |||
469 | 517 | ||
470 | rproc->num_traces++; | 518 | rproc->num_traces++; |
471 | 519 | ||
472 | dev_dbg(dev, "%s added: va %p, da 0x%llx, len 0x%x\n", name, ptr, | 520 | dev_dbg(dev, "%s added: va %p, da 0x%x, len 0x%x\n", name, ptr, |
473 | rsc->da, rsc->len); | 521 | rsc->da, rsc->len); |
474 | 522 | ||
475 | return 0; | 523 | return 0; |
@@ -479,6 +527,7 @@ static int rproc_handle_trace(struct rproc *rproc, struct fw_resource *rsc) | |||
479 | * rproc_handle_devmem() - handle devmem resource entry | 527 | * rproc_handle_devmem() - handle devmem resource entry |
480 | * @rproc: remote processor handle | 528 | * @rproc: remote processor handle |
481 | * @rsc: the devmem resource entry | 529 | * @rsc: the devmem resource entry |
530 | * @avail: size of available data (for sanity checking the image) | ||
482 | * | 531 | * |
483 | * Remote processors commonly need to access certain on-chip peripherals. | 532 | * Remote processors commonly need to access certain on-chip peripherals. |
484 | * | 533 | * |
@@ -499,7 +548,8 @@ static int rproc_handle_trace(struct rproc *rproc, struct fw_resource *rsc) | |||
499 | * and not allow firmwares to request access to physical addresses that | 548 | * and not allow firmwares to request access to physical addresses that |
500 | * are outside those ranges. | 549 | * are outside those ranges. |
501 | */ | 550 | */ |
502 | static int rproc_handle_devmem(struct rproc *rproc, struct fw_resource *rsc) | 551 | static int rproc_handle_devmem(struct rproc *rproc, struct fw_rsc_devmem *rsc, |
552 | int avail) | ||
503 | { | 553 | { |
504 | struct rproc_mem_entry *mapping; | 554 | struct rproc_mem_entry *mapping; |
505 | int ret; | 555 | int ret; |
@@ -508,6 +558,17 @@ static int rproc_handle_devmem(struct rproc *rproc, struct fw_resource *rsc) | |||
508 | if (!rproc->domain) | 558 | if (!rproc->domain) |
509 | return -EINVAL; | 559 | return -EINVAL; |
510 | 560 | ||
561 | if (sizeof(*rsc) > avail) { | ||
562 | dev_err(rproc->dev, "devmem rsc is truncated\n"); | ||
563 | return -EINVAL; | ||
564 | } | ||
565 | |||
566 | /* make sure reserved bytes are zeroes */ | ||
567 | if (rsc->reserved) { | ||
568 | dev_err(rproc->dev, "devmem rsc has non zero reserved bytes\n"); | ||
569 | return -EINVAL; | ||
570 | } | ||
571 | |||
511 | mapping = kzalloc(sizeof(*mapping), GFP_KERNEL); | 572 | mapping = kzalloc(sizeof(*mapping), GFP_KERNEL); |
512 | if (!mapping) { | 573 | if (!mapping) { |
513 | dev_err(rproc->dev, "kzalloc mapping failed\n"); | 574 | dev_err(rproc->dev, "kzalloc mapping failed\n"); |
@@ -531,7 +592,7 @@ static int rproc_handle_devmem(struct rproc *rproc, struct fw_resource *rsc) | |||
531 | mapping->len = rsc->len; | 592 | mapping->len = rsc->len; |
532 | list_add_tail(&mapping->node, &rproc->mappings); | 593 | list_add_tail(&mapping->node, &rproc->mappings); |
533 | 594 | ||
534 | dev_dbg(rproc->dev, "mapped devmem pa 0x%llx, da 0x%llx, len 0x%x\n", | 595 | dev_dbg(rproc->dev, "mapped devmem pa 0x%x, da 0x%x, len 0x%x\n", |
535 | rsc->pa, rsc->da, rsc->len); | 596 | rsc->pa, rsc->da, rsc->len); |
536 | 597 | ||
537 | return 0; | 598 | return 0; |
@@ -545,6 +606,7 @@ out: | |||
545 | * rproc_handle_carveout() - handle phys contig memory allocation requests | 606 | * rproc_handle_carveout() - handle phys contig memory allocation requests |
546 | * @rproc: rproc handle | 607 | * @rproc: rproc handle |
547 | * @rsc: the resource entry | 608 | * @rsc: the resource entry |
609 | * @avail: size of available data (for image validation) | ||
548 | * | 610 | * |
549 | * This function will handle firmware requests for allocation of physically | 611 | * This function will handle firmware requests for allocation of physically |
550 | * contiguous memory regions. | 612 | * contiguous memory regions. |
@@ -558,7 +620,8 @@ out: | |||
558 | * needed to map it (in case @rproc is using an IOMMU). Reducing the TLB | 620 | * needed to map it (in case @rproc is using an IOMMU). Reducing the TLB |
559 | * pressure is important; it may have a substantial impact on performance. | 621 | * pressure is important; it may have a substantial impact on performance. |
560 | */ | 622 | */ |
561 | static int rproc_handle_carveout(struct rproc *rproc, struct fw_resource *rsc) | 623 | static int rproc_handle_carveout(struct rproc *rproc, |
624 | struct fw_rsc_carveout *rsc, int avail) | ||
562 | { | 625 | { |
563 | struct rproc_mem_entry *carveout, *mapping; | 626 | struct rproc_mem_entry *carveout, *mapping; |
564 | struct device *dev = rproc->dev; | 627 | struct device *dev = rproc->dev; |
@@ -566,6 +629,20 @@ static int rproc_handle_carveout(struct rproc *rproc, struct fw_resource *rsc) | |||
566 | void *va; | 629 | void *va; |
567 | int ret; | 630 | int ret; |
568 | 631 | ||
632 | if (sizeof(*rsc) > avail) { | ||
633 | dev_err(rproc->dev, "carveout rsc is truncated\n"); | ||
634 | return -EINVAL; | ||
635 | } | ||
636 | |||
637 | /* make sure reserved bytes are zeroes */ | ||
638 | if (rsc->reserved) { | ||
639 | dev_err(dev, "carveout rsc has non zero reserved bytes\n"); | ||
640 | return -EINVAL; | ||
641 | } | ||
642 | |||
643 | dev_dbg(dev, "carveout rsc: da %x, pa %x, len %x, flags %x\n", | ||
644 | rsc->da, rsc->pa, rsc->len, rsc->flags); | ||
645 | |||
569 | mapping = kzalloc(sizeof(*mapping), GFP_KERNEL); | 646 | mapping = kzalloc(sizeof(*mapping), GFP_KERNEL); |
570 | if (!mapping) { | 647 | if (!mapping) { |
571 | dev_err(dev, "kzalloc mapping failed\n"); | 648 | dev_err(dev, "kzalloc mapping failed\n"); |
@@ -624,7 +701,7 @@ static int rproc_handle_carveout(struct rproc *rproc, struct fw_resource *rsc) | |||
624 | mapping->len = rsc->len; | 701 | mapping->len = rsc->len; |
625 | list_add_tail(&mapping->node, &rproc->mappings); | 702 | list_add_tail(&mapping->node, &rproc->mappings); |
626 | 703 | ||
627 | dev_dbg(dev, "carveout mapped 0x%llx to 0x%x\n", rsc->da, dma); | 704 | dev_dbg(dev, "carveout mapped 0x%x to 0x%x\n", rsc->da, dma); |
628 | 705 | ||
629 | /* | 706 | /* |
630 | * Some remote processors might need to know the pa | 707 | * Some remote processors might need to know the pa |
@@ -665,36 +742,44 @@ free_mapping: | |||
665 | * enum fw_resource_type. | 742 | * enum fw_resource_type. |
666 | */ | 743 | */ |
667 | static rproc_handle_resource_t rproc_handle_rsc[] = { | 744 | static rproc_handle_resource_t rproc_handle_rsc[] = { |
668 | [RSC_CARVEOUT] = rproc_handle_carveout, | 745 | [RSC_CARVEOUT] = (rproc_handle_resource_t)rproc_handle_carveout, |
669 | [RSC_DEVMEM] = rproc_handle_devmem, | 746 | [RSC_DEVMEM] = (rproc_handle_resource_t)rproc_handle_devmem, |
670 | [RSC_TRACE] = rproc_handle_trace, | 747 | [RSC_TRACE] = (rproc_handle_resource_t)rproc_handle_trace, |
671 | [RSC_VRING] = rproc_handle_vring, | 748 | [RSC_VDEV] = NULL, /* VDEVs were handled upon registrarion */ |
672 | [RSC_VIRTIO_DEV] = NULL, /* handled early upon registration */ | ||
673 | }; | 749 | }; |
674 | 750 | ||
675 | /* handle firmware resource entries before booting the remote processor */ | 751 | /* handle firmware resource entries before booting the remote processor */ |
676 | static int | 752 | static int |
677 | rproc_handle_boot_rsc(struct rproc *rproc, struct fw_resource *rsc, int len) | 753 | rproc_handle_boot_rsc(struct rproc *rproc, struct resource_table *table, int len) |
678 | { | 754 | { |
679 | struct device *dev = rproc->dev; | 755 | struct device *dev = rproc->dev; |
680 | rproc_handle_resource_t handler; | 756 | rproc_handle_resource_t handler; |
681 | int ret = 0; | 757 | int ret = 0, i; |
758 | |||
759 | for (i = 0; i < table->num; i++) { | ||
760 | int offset = table->offset[i]; | ||
761 | struct fw_rsc_hdr *hdr = (void *)table + offset; | ||
762 | int avail = len - offset - sizeof(*hdr); | ||
763 | void *rsc = (void *)hdr + sizeof(*hdr); | ||
764 | |||
765 | /* make sure table isn't truncated */ | ||
766 | if (avail < 0) { | ||
767 | dev_err(dev, "rsc table is truncated\n"); | ||
768 | return -EINVAL; | ||
769 | } | ||
682 | 770 | ||
683 | for (; len >= sizeof(*rsc); rsc++, len -= sizeof(*rsc)) { | 771 | dev_dbg(dev, "rsc: type %d\n", hdr->type); |
684 | dev_dbg(dev, "rsc: type %d, da 0x%llx, pa 0x%llx, len 0x%x, " | ||
685 | "id %d, name %s, flags %x\n", rsc->type, rsc->da, | ||
686 | rsc->pa, rsc->len, rsc->id, rsc->name, rsc->flags); | ||
687 | 772 | ||
688 | if (rsc->type >= RSC_LAST) { | 773 | if (hdr->type >= RSC_LAST) { |
689 | dev_warn(dev, "unsupported resource %d\n", rsc->type); | 774 | dev_warn(dev, "unsupported resource %d\n", hdr->type); |
690 | continue; | 775 | continue; |
691 | } | 776 | } |
692 | 777 | ||
693 | handler = rproc_handle_rsc[rsc->type]; | 778 | handler = rproc_handle_rsc[hdr->type]; |
694 | if (!handler) | 779 | if (!handler) |
695 | continue; | 780 | continue; |
696 | 781 | ||
697 | ret = handler(rproc, rsc); | 782 | ret = handler(rproc, rsc, avail); |
698 | if (ret) | 783 | if (ret) |
699 | break; | 784 | break; |
700 | } | 785 | } |
@@ -704,47 +789,64 @@ rproc_handle_boot_rsc(struct rproc *rproc, struct fw_resource *rsc, int len) | |||
704 | 789 | ||
705 | /* handle firmware resource entries while registering the remote processor */ | 790 | /* handle firmware resource entries while registering the remote processor */ |
706 | static int | 791 | static int |
707 | rproc_handle_virtio_rsc(struct rproc *rproc, struct fw_resource *rsc, int len) | 792 | rproc_handle_virtio_rsc(struct rproc *rproc, struct resource_table *table, int len) |
708 | { | 793 | { |
709 | struct device *dev = rproc->dev; | 794 | struct device *dev = rproc->dev; |
710 | int ret = -ENODEV; | 795 | int ret = 0, i; |
796 | |||
797 | for (i = 0; i < table->num; i++) { | ||
798 | int offset = table->offset[i]; | ||
799 | struct fw_rsc_hdr *hdr = (void *)table + offset; | ||
800 | int avail = len - offset - sizeof(*hdr); | ||
801 | struct fw_rsc_vdev *vrsc; | ||
802 | |||
803 | /* make sure table isn't truncated */ | ||
804 | if (avail < 0) { | ||
805 | dev_err(dev, "rsc table is truncated\n"); | ||
806 | return -EINVAL; | ||
807 | } | ||
808 | |||
809 | dev_dbg(dev, "%s: rsc type %d\n", __func__, hdr->type); | ||
810 | |||
811 | if (hdr->type != RSC_VDEV) | ||
812 | continue; | ||
813 | |||
814 | vrsc = (struct fw_rsc_vdev *)hdr->data; | ||
711 | 815 | ||
712 | for (; len >= sizeof(*rsc); rsc++, len -= sizeof(*rsc)) | 816 | ret = rproc_handle_vdev(rproc, vrsc, avail); |
713 | if (rsc->type == RSC_VIRTIO_DEV) { | 817 | if (ret) |
714 | dev_dbg(dev, "found vdev %d/%s features %llx\n", | ||
715 | rsc->flags, rsc->name, rsc->da); | ||
716 | ret = rproc_handle_virtio_hdr(rproc, rsc); | ||
717 | break; | 818 | break; |
718 | } | 819 | } |
719 | 820 | ||
720 | return ret; | 821 | return ret; |
721 | } | 822 | } |
722 | 823 | ||
723 | /** | 824 | /** |
724 | * rproc_handle_resources() - find and handle the resource table | 825 | * rproc_find_rsc_table() - find the resource table |
725 | * @rproc: the rproc handle | 826 | * @rproc: the rproc handle |
726 | * @elf_data: the content of the ELF firmware image | 827 | * @elf_data: the content of the ELF firmware image |
727 | * @len: firmware size (in bytes) | 828 | * @len: firmware size (in bytes) |
728 | * @handler: function that should be used to handle the resource table | 829 | * @tablesz: place holder for providing back the table size |
729 | * | 830 | * |
730 | * This function finds the resource table inside the remote processor's | 831 | * This function finds the resource table inside the remote processor's |
731 | * firmware, and invoke a user-supplied handler with it (we have two | 832 | * firmware. It is used both upon the registration of @rproc (in order |
732 | * possible handlers: one is invoked upon registration of @rproc, | 833 | * to look for and register the supported virito devices), and when the |
733 | * in order to register the supported virito devices, and the other is | 834 | * @rproc is booted. |
734 | * invoked when @rproc is actually booted). | 835 | * |
735 | * | 836 | * Returns the pointer to the resource table if it is found, and write its |
736 | * Currently this function fails if a resource table doesn't exist. | 837 | * size into @tablesz. If a valid table isn't found, NULL is returned |
737 | * This restriction will be removed when we'll start supporting remote | 838 | * (and @tablesz isn't set). |
738 | * processors that don't need a resource table. | ||
739 | */ | 839 | */ |
740 | static int rproc_handle_resources(struct rproc *rproc, const u8 *elf_data, | 840 | static struct resource_table * |
741 | size_t len, rproc_handle_resources_t handler) | 841 | rproc_find_rsc_table(struct rproc *rproc, const u8 *elf_data, size_t len, |
742 | 842 | int *tablesz) | |
743 | { | 843 | { |
744 | struct elf32_hdr *ehdr; | 844 | struct elf32_hdr *ehdr; |
745 | struct elf32_shdr *shdr; | 845 | struct elf32_shdr *shdr; |
746 | const char *name_table; | 846 | const char *name_table; |
747 | int i, ret = -EINVAL; | 847 | struct device *dev = rproc->dev; |
848 | struct resource_table *table = NULL; | ||
849 | int i; | ||
748 | 850 | ||
749 | ehdr = (struct elf32_hdr *)elf_data; | 851 | ehdr = (struct elf32_hdr *)elf_data; |
750 | shdr = (struct elf32_shdr *)(elf_data + ehdr->e_shoff); | 852 | shdr = (struct elf32_shdr *)(elf_data + ehdr->e_shoff); |
@@ -752,24 +854,50 @@ static int rproc_handle_resources(struct rproc *rproc, const u8 *elf_data, | |||
752 | 854 | ||
753 | /* look for the resource table and handle it */ | 855 | /* look for the resource table and handle it */ |
754 | for (i = 0; i < ehdr->e_shnum; i++, shdr++) { | 856 | for (i = 0; i < ehdr->e_shnum; i++, shdr++) { |
755 | if (!strcmp(name_table + shdr->sh_name, ".resource_table")) { | 857 | int size = shdr->sh_size; |
756 | struct fw_resource *table = (struct fw_resource *) | 858 | int offset = shdr->sh_offset; |
757 | (elf_data + shdr->sh_offset); | 859 | |
860 | if (strcmp(name_table + shdr->sh_name, ".resource_table")) | ||
861 | continue; | ||
758 | 862 | ||
759 | if (shdr->sh_offset + shdr->sh_size > len) { | 863 | table = (struct resource_table *)(elf_data + offset); |
760 | dev_err(rproc->dev, | ||
761 | "truncated fw: need 0x%x avail 0x%x\n", | ||
762 | shdr->sh_offset + shdr->sh_size, len); | ||
763 | ret = -EINVAL; | ||
764 | } | ||
765 | 864 | ||
766 | ret = handler(rproc, table, shdr->sh_size); | 865 | /* make sure we have the entire table */ |
866 | if (offset + size > len) { | ||
867 | dev_err(dev, "resource table truncated\n"); | ||
868 | return NULL; | ||
869 | } | ||
767 | 870 | ||
768 | break; | 871 | /* make sure table has at least the header */ |
872 | if (sizeof(struct resource_table) > size) { | ||
873 | dev_err(dev, "header-less resource table\n"); | ||
874 | return NULL; | ||
875 | } | ||
876 | |||
877 | /* we don't support any version beyond the first */ | ||
878 | if (table->ver != 1) { | ||
879 | dev_err(dev, "unsupported fw ver: %d\n", table->ver); | ||
880 | return NULL; | ||
881 | } | ||
882 | |||
883 | /* make sure reserved bytes are zeroes */ | ||
884 | if (table->reserved[0] || table->reserved[1]) { | ||
885 | dev_err(dev, "non zero reserved bytes\n"); | ||
886 | return NULL; | ||
887 | } | ||
888 | |||
889 | /* make sure the offsets array isn't truncated */ | ||
890 | if (table->num * sizeof(table->offset[0]) + | ||
891 | sizeof(struct resource_table) > size) { | ||
892 | dev_err(dev, "resource table incomplete\n"); | ||
893 | return NULL; | ||
769 | } | 894 | } |
895 | |||
896 | *tablesz = shdr->sh_size; | ||
897 | break; | ||
770 | } | 898 | } |
771 | 899 | ||
772 | return ret; | 900 | return table; |
773 | } | 901 | } |
774 | 902 | ||
775 | /** | 903 | /** |
@@ -777,14 +905,12 @@ static int rproc_handle_resources(struct rproc *rproc, const u8 *elf_data, | |||
777 | * @rproc: rproc handle | 905 | * @rproc: rproc handle |
778 | * | 906 | * |
779 | * This function will free all resources acquired for @rproc, and it | 907 | * This function will free all resources acquired for @rproc, and it |
780 | * is called when @rproc shuts down, or just failed booting. | 908 | * is called whenever @rproc either shuts down or fails to boot. |
781 | */ | 909 | */ |
782 | static void rproc_resource_cleanup(struct rproc *rproc) | 910 | static void rproc_resource_cleanup(struct rproc *rproc) |
783 | { | 911 | { |
784 | struct rproc_mem_entry *entry, *tmp; | 912 | struct rproc_mem_entry *entry, *tmp; |
785 | struct device *dev = rproc->dev; | 913 | struct device *dev = rproc->dev; |
786 | struct rproc_vdev *rvdev = rproc->rvdev; | ||
787 | int i; | ||
788 | 914 | ||
789 | /* clean up debugfs trace entries */ | 915 | /* clean up debugfs trace entries */ |
790 | list_for_each_entry_safe(entry, tmp, &rproc->traces, node) { | 916 | list_for_each_entry_safe(entry, tmp, &rproc->traces, node) { |
@@ -794,23 +920,6 @@ static void rproc_resource_cleanup(struct rproc *rproc) | |||
794 | kfree(entry); | 920 | kfree(entry); |
795 | } | 921 | } |
796 | 922 | ||
797 | /* free the coherent memory allocated for the vrings */ | ||
798 | for (i = 0; rvdev && i < ARRAY_SIZE(rvdev->vring); i++) { | ||
799 | int qsz = rvdev->vring[i].len; | ||
800 | void *va = rvdev->vring[i].va; | ||
801 | int dma = rvdev->vring[i].dma; | ||
802 | |||
803 | /* virtqueue size is expressed in number of buffers supported */ | ||
804 | if (qsz) { | ||
805 | /* how many bytes does this vring really occupy ? */ | ||
806 | int size = PAGE_ALIGN(vring_size(qsz, AMP_VRING_ALIGN)); | ||
807 | |||
808 | dma_free_coherent(rproc->dev, size, va, dma); | ||
809 | |||
810 | rvdev->vring[i].len = 0; | ||
811 | } | ||
812 | } | ||
813 | |||
814 | /* clean up carveout allocations */ | 923 | /* clean up carveout allocations */ |
815 | list_for_each_entry_safe(entry, tmp, &rproc->carveouts, node) { | 924 | list_for_each_entry_safe(entry, tmp, &rproc->carveouts, node) { |
816 | dma_free_coherent(dev, entry->len, entry->va, entry->dma); | 925 | dma_free_coherent(dev, entry->len, entry->va, entry->dma); |
@@ -840,6 +949,7 @@ static int rproc_fw_sanity_check(struct rproc *rproc, const struct firmware *fw) | |||
840 | const char *name = rproc->firmware; | 949 | const char *name = rproc->firmware; |
841 | struct device *dev = rproc->dev; | 950 | struct device *dev = rproc->dev; |
842 | struct elf32_hdr *ehdr; | 951 | struct elf32_hdr *ehdr; |
952 | char class; | ||
843 | 953 | ||
844 | if (!fw) { | 954 | if (!fw) { |
845 | dev_err(dev, "failed to load %s\n", name); | 955 | dev_err(dev, "failed to load %s\n", name); |
@@ -853,6 +963,13 @@ static int rproc_fw_sanity_check(struct rproc *rproc, const struct firmware *fw) | |||
853 | 963 | ||
854 | ehdr = (struct elf32_hdr *)fw->data; | 964 | ehdr = (struct elf32_hdr *)fw->data; |
855 | 965 | ||
966 | /* We only support ELF32 at this point */ | ||
967 | class = ehdr->e_ident[EI_CLASS]; | ||
968 | if (class != ELFCLASS32) { | ||
969 | dev_err(dev, "Unsupported class: %d\n", class); | ||
970 | return -EINVAL; | ||
971 | } | ||
972 | |||
856 | /* We assume the firmware has the same endianess as the host */ | 973 | /* We assume the firmware has the same endianess as the host */ |
857 | # ifdef __LITTLE_ENDIAN | 974 | # ifdef __LITTLE_ENDIAN |
858 | if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) { | 975 | if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) { |
@@ -894,7 +1011,8 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw) | |||
894 | struct device *dev = rproc->dev; | 1011 | struct device *dev = rproc->dev; |
895 | const char *name = rproc->firmware; | 1012 | const char *name = rproc->firmware; |
896 | struct elf32_hdr *ehdr; | 1013 | struct elf32_hdr *ehdr; |
897 | int ret; | 1014 | struct resource_table *table; |
1015 | int ret, tablesz; | ||
898 | 1016 | ||
899 | ret = rproc_fw_sanity_check(rproc, fw); | 1017 | ret = rproc_fw_sanity_check(rproc, fw); |
900 | if (ret) | 1018 | if (ret) |
@@ -921,9 +1039,13 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw) | |||
921 | */ | 1039 | */ |
922 | rproc->bootaddr = ehdr->e_entry; | 1040 | rproc->bootaddr = ehdr->e_entry; |
923 | 1041 | ||
1042 | /* look for the resource table */ | ||
1043 | table = rproc_find_rsc_table(rproc, fw->data, fw->size, &tablesz); | ||
1044 | if (!table) | ||
1045 | goto clean_up; | ||
1046 | |||
924 | /* handle fw resources which are required to boot rproc */ | 1047 | /* handle fw resources which are required to boot rproc */ |
925 | ret = rproc_handle_resources(rproc, fw->data, fw->size, | 1048 | ret = rproc_handle_boot_rsc(rproc, table, tablesz); |
926 | rproc_handle_boot_rsc); | ||
927 | if (ret) { | 1049 | if (ret) { |
928 | dev_err(dev, "Failed to process resources: %d\n", ret); | 1050 | dev_err(dev, "Failed to process resources: %d\n", ret); |
929 | goto clean_up; | 1051 | goto clean_up; |
@@ -966,22 +1088,19 @@ clean_up: | |||
966 | static void rproc_fw_config_virtio(const struct firmware *fw, void *context) | 1088 | static void rproc_fw_config_virtio(const struct firmware *fw, void *context) |
967 | { | 1089 | { |
968 | struct rproc *rproc = context; | 1090 | struct rproc *rproc = context; |
969 | struct device *dev = rproc->dev; | 1091 | struct resource_table *table; |
970 | int ret; | 1092 | int ret, tablesz; |
971 | 1093 | ||
972 | if (rproc_fw_sanity_check(rproc, fw) < 0) | 1094 | if (rproc_fw_sanity_check(rproc, fw) < 0) |
973 | goto out; | 1095 | goto out; |
974 | 1096 | ||
975 | /* does the fw supports any virtio devices ? */ | 1097 | /* look for the resource table */ |
976 | ret = rproc_handle_resources(rproc, fw->data, fw->size, | 1098 | table = rproc_find_rsc_table(rproc, fw->data, fw->size, &tablesz); |
977 | rproc_handle_virtio_rsc); | 1099 | if (!table) |
978 | if (ret) { | ||
979 | dev_info(dev, "No fw virtio device was found\n"); | ||
980 | goto out; | 1100 | goto out; |
981 | } | ||
982 | 1101 | ||
983 | /* add the virtio device (currently only rpmsg vdevs are supported) */ | 1102 | /* look for virtio devices and register them */ |
984 | ret = rproc_add_rpmsg_vdev(rproc); | 1103 | ret = rproc_handle_virtio_rsc(rproc, table, tablesz); |
985 | if (ret) | 1104 | if (ret) |
986 | goto out; | 1105 | goto out; |
987 | 1106 | ||
@@ -1146,13 +1265,23 @@ EXPORT_SYMBOL(rproc_shutdown); | |||
1146 | void rproc_release(struct kref *kref) | 1265 | void rproc_release(struct kref *kref) |
1147 | { | 1266 | { |
1148 | struct rproc *rproc = container_of(kref, struct rproc, refcount); | 1267 | struct rproc *rproc = container_of(kref, struct rproc, refcount); |
1268 | struct rproc_vdev *rvdev, *rvtmp; | ||
1149 | 1269 | ||
1150 | dev_info(rproc->dev, "removing %s\n", rproc->name); | 1270 | dev_info(rproc->dev, "removing %s\n", rproc->name); |
1151 | 1271 | ||
1152 | rproc_delete_debug_dir(rproc); | 1272 | rproc_delete_debug_dir(rproc); |
1153 | 1273 | ||
1154 | /* at this point no one holds a reference to rproc anymore */ | 1274 | /* clean up remote vdev entries */ |
1155 | kfree(rproc); | 1275 | list_for_each_entry_safe(rvdev, rvtmp, &rproc->rvdevs, node) { |
1276 | __rproc_free_vrings(rvdev, RVDEV_NUM_VRINGS); | ||
1277 | list_del(&rvdev->node); | ||
1278 | } | ||
1279 | |||
1280 | /* | ||
1281 | * At this point no one holds a reference to rproc anymore, | ||
1282 | * so we can directly unroll rproc_alloc() | ||
1283 | */ | ||
1284 | rproc_free(rproc); | ||
1156 | } | 1285 | } |
1157 | 1286 | ||
1158 | /* will be called when an rproc is added to the rprocs klist */ | 1287 | /* will be called when an rproc is added to the rprocs klist */ |
@@ -1196,7 +1325,7 @@ static struct rproc *next_rproc(struct klist_iter *i) | |||
1196 | * use rproc_put() to decrement it back once rproc isn't needed anymore. | 1325 | * use rproc_put() to decrement it back once rproc isn't needed anymore. |
1197 | * | 1326 | * |
1198 | * Note: currently this function (and its counterpart rproc_put()) are not | 1327 | * Note: currently this function (and its counterpart rproc_put()) are not |
1199 | * used anymore by the rpmsg subsystem. We need to scrutinize the use cases | 1328 | * being used. We need to scrutinize the use cases |
1200 | * that still need them, and see if we can migrate them to use the non | 1329 | * that still need them, and see if we can migrate them to use the non |
1201 | * name-based boot/shutdown interface. | 1330 | * name-based boot/shutdown interface. |
1202 | */ | 1331 | */ |
@@ -1271,11 +1400,8 @@ EXPORT_SYMBOL(rproc_put); | |||
1271 | * firmware. | 1400 | * firmware. |
1272 | * | 1401 | * |
1273 | * If found, those virtio devices will be created and added, so as a result | 1402 | * If found, those virtio devices will be created and added, so as a result |
1274 | * of registering this remote processor, additional virtio drivers will be | 1403 | * of registering this remote processor, additional virtio drivers might be |
1275 | * probed. | 1404 | * probed. |
1276 | * | ||
1277 | * Currently, though, we only support a single RPMSG virtio vdev per remote | ||
1278 | * processor. | ||
1279 | */ | 1405 | */ |
1280 | int rproc_register(struct rproc *rproc) | 1406 | int rproc_register(struct rproc *rproc) |
1281 | { | 1407 | { |
@@ -1298,7 +1424,7 @@ int rproc_register(struct rproc *rproc) | |||
1298 | 1424 | ||
1299 | /* | 1425 | /* |
1300 | * We must retrieve early virtio configuration info from | 1426 | * We must retrieve early virtio configuration info from |
1301 | * the firmware (e.g. whether to register a virtio rpmsg device, | 1427 | * the firmware (e.g. whether to register a virtio device, |
1302 | * what virtio features does it support, ...). | 1428 | * what virtio features does it support, ...). |
1303 | * | 1429 | * |
1304 | * We're initiating an asynchronous firmware loading, so we can | 1430 | * We're initiating an asynchronous firmware loading, so we can |
@@ -1367,9 +1493,12 @@ struct rproc *rproc_alloc(struct device *dev, const char *name, | |||
1367 | 1493 | ||
1368 | mutex_init(&rproc->lock); | 1494 | mutex_init(&rproc->lock); |
1369 | 1495 | ||
1496 | idr_init(&rproc->notifyids); | ||
1497 | |||
1370 | INIT_LIST_HEAD(&rproc->carveouts); | 1498 | INIT_LIST_HEAD(&rproc->carveouts); |
1371 | INIT_LIST_HEAD(&rproc->mappings); | 1499 | INIT_LIST_HEAD(&rproc->mappings); |
1372 | INIT_LIST_HEAD(&rproc->traces); | 1500 | INIT_LIST_HEAD(&rproc->traces); |
1501 | INIT_LIST_HEAD(&rproc->rvdevs); | ||
1373 | 1502 | ||
1374 | rproc->state = RPROC_OFFLINE; | 1503 | rproc->state = RPROC_OFFLINE; |
1375 | 1504 | ||
@@ -1389,6 +1518,9 @@ EXPORT_SYMBOL(rproc_alloc); | |||
1389 | */ | 1518 | */ |
1390 | void rproc_free(struct rproc *rproc) | 1519 | void rproc_free(struct rproc *rproc) |
1391 | { | 1520 | { |
1521 | idr_remove_all(&rproc->notifyids); | ||
1522 | idr_destroy(&rproc->notifyids); | ||
1523 | |||
1392 | kfree(rproc); | 1524 | kfree(rproc); |
1393 | } | 1525 | } |
1394 | EXPORT_SYMBOL(rproc_free); | 1526 | EXPORT_SYMBOL(rproc_free); |
@@ -1415,18 +1547,22 @@ EXPORT_SYMBOL(rproc_free); | |||
1415 | */ | 1547 | */ |
1416 | int rproc_unregister(struct rproc *rproc) | 1548 | int rproc_unregister(struct rproc *rproc) |
1417 | { | 1549 | { |
1550 | struct rproc_vdev *rvdev; | ||
1551 | |||
1418 | if (!rproc) | 1552 | if (!rproc) |
1419 | return -EINVAL; | 1553 | return -EINVAL; |
1420 | 1554 | ||
1421 | /* if rproc is just being registered, wait */ | 1555 | /* if rproc is just being registered, wait */ |
1422 | wait_for_completion(&rproc->firmware_loading_complete); | 1556 | wait_for_completion(&rproc->firmware_loading_complete); |
1423 | 1557 | ||
1424 | /* was an rpmsg vdev created ? */ | 1558 | /* clean up remote vdev entries */ |
1425 | if (rproc->rvdev) | 1559 | list_for_each_entry(rvdev, &rproc->rvdevs, node) |
1426 | rproc_remove_rpmsg_vdev(rproc); | 1560 | rproc_remove_virtio_dev(rvdev); |
1427 | 1561 | ||
1428 | klist_remove(&rproc->node); | 1562 | /* the rproc is downref'ed as soon as it's removed from the klist */ |
1563 | klist_del(&rproc->node); | ||
1429 | 1564 | ||
1565 | /* the rproc will only be released after its refcount drops to zero */ | ||
1430 | kref_put(&rproc->refcount, rproc_release); | 1566 | kref_put(&rproc->refcount, rproc_release); |
1431 | 1567 | ||
1432 | return 0; | 1568 | return 0; |
diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h index 8b2fc40e92d0..9f336d6bdef3 100644 --- a/drivers/remoteproc/remoteproc_internal.h +++ b/drivers/remoteproc/remoteproc_internal.h | |||
@@ -28,9 +28,9 @@ struct rproc; | |||
28 | void rproc_release(struct kref *kref); | 28 | void rproc_release(struct kref *kref); |
29 | irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int vq_id); | 29 | irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int vq_id); |
30 | 30 | ||
31 | /* from remoteproc_rpmsg.c */ | 31 | /* from remoteproc_virtio.c */ |
32 | int rproc_add_rpmsg_vdev(struct rproc *); | 32 | int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id); |
33 | void rproc_remove_rpmsg_vdev(struct rproc *rproc); | 33 | void rproc_remove_virtio_dev(struct rproc_vdev *rvdev); |
34 | 34 | ||
35 | /* from remoteproc_debugfs.c */ | 35 | /* from remoteproc_debugfs.c */ |
36 | void rproc_remove_trace_file(struct dentry *tfile); | 36 | void rproc_remove_trace_file(struct dentry *tfile); |
diff --git a/drivers/remoteproc/remoteproc_rpmsg.c b/drivers/remoteproc/remoteproc_virtio.c index 4f73e811bb80..ecf612130750 100644 --- a/drivers/remoteproc/remoteproc_rpmsg.c +++ b/drivers/remoteproc/remoteproc_virtio.c | |||
@@ -19,7 +19,6 @@ | |||
19 | 19 | ||
20 | #include <linux/export.h> | 20 | #include <linux/export.h> |
21 | #include <linux/remoteproc.h> | 21 | #include <linux/remoteproc.h> |
22 | #include <linux/rpmsg.h> | ||
23 | #include <linux/virtio.h> | 22 | #include <linux/virtio.h> |
24 | #include <linux/virtio_config.h> | 23 | #include <linux/virtio_config.h> |
25 | #include <linux/virtio_ids.h> | 24 | #include <linux/virtio_ids.h> |
@@ -30,45 +29,41 @@ | |||
30 | 29 | ||
31 | #include "remoteproc_internal.h" | 30 | #include "remoteproc_internal.h" |
32 | 31 | ||
33 | /** | ||
34 | * struct rproc_virtio_vq_info - virtqueue state | ||
35 | * @vq_id: a unique index of this virtqueue (unique for this @rproc) | ||
36 | * @rproc: handle to the remote processor | ||
37 | * | ||
38 | * Such a struct will be maintained for every virtqueue we're | ||
39 | * using to communicate with the remote processor | ||
40 | */ | ||
41 | struct rproc_virtio_vq_info { | ||
42 | __u16 vq_id; | ||
43 | struct rproc *rproc; | ||
44 | }; | ||
45 | |||
46 | /* kick the remote processor, and let it know which virtqueue to poke at */ | 32 | /* kick the remote processor, and let it know which virtqueue to poke at */ |
47 | static void rproc_virtio_notify(struct virtqueue *vq) | 33 | static void rproc_virtio_notify(struct virtqueue *vq) |
48 | { | 34 | { |
49 | struct rproc_virtio_vq_info *rpvq = vq->priv; | 35 | struct rproc_vring *rvring = vq->priv; |
50 | struct rproc *rproc = rpvq->rproc; | 36 | struct rproc *rproc = rvring->rvdev->rproc; |
37 | int notifyid = rvring->notifyid; | ||
51 | 38 | ||
52 | dev_dbg(rproc->dev, "kicking vq id: %d\n", rpvq->vq_id); | 39 | dev_dbg(rproc->dev, "kicking vq index: %d\n", notifyid); |
53 | 40 | ||
54 | rproc->ops->kick(rproc, rpvq->vq_id); | 41 | rproc->ops->kick(rproc, notifyid); |
55 | } | 42 | } |
56 | 43 | ||
57 | /** | 44 | /** |
58 | * rproc_vq_interrupt() - tell remoteproc that a virtqueue is interrupted | 45 | * rproc_vq_interrupt() - tell remoteproc that a virtqueue is interrupted |
59 | * @rproc: handle to the remote processor | 46 | * @rproc: handle to the remote processor |
60 | * @vq_id: index of the signalled virtqueue | 47 | * @notifyid: index of the signalled virtqueue (unique per this @rproc) |
61 | * | 48 | * |
62 | * This function should be called by the platform-specific rproc driver, | 49 | * This function should be called by the platform-specific rproc driver, |
63 | * when the remote processor signals that a specific virtqueue has pending | 50 | * when the remote processor signals that a specific virtqueue has pending |
64 | * messages available. | 51 | * messages available. |
65 | * | 52 | * |
66 | * Returns IRQ_NONE if no message was found in the @vq_id virtqueue, | 53 | * Returns IRQ_NONE if no message was found in the @notifyid virtqueue, |
67 | * and otherwise returns IRQ_HANDLED. | 54 | * and otherwise returns IRQ_HANDLED. |
68 | */ | 55 | */ |
69 | irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int vq_id) | 56 | irqreturn_t rproc_vq_interrupt(struct rproc *rproc, int notifyid) |
70 | { | 57 | { |
71 | return vring_interrupt(0, rproc->rvdev->vq[vq_id]); | 58 | struct rproc_vring *rvring; |
59 | |||
60 | dev_dbg(rproc->dev, "vq index %d is interrupted\n", notifyid); | ||
61 | |||
62 | rvring = idr_find(&rproc->notifyids, notifyid); | ||
63 | if (!rvring || !rvring->vq) | ||
64 | return IRQ_NONE; | ||
65 | |||
66 | return vring_interrupt(0, rvring->vq); | ||
72 | } | 67 | } |
73 | EXPORT_SYMBOL(rproc_vq_interrupt); | 68 | EXPORT_SYMBOL(rproc_vq_interrupt); |
74 | 69 | ||
@@ -77,60 +72,60 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev, | |||
77 | void (*callback)(struct virtqueue *vq), | 72 | void (*callback)(struct virtqueue *vq), |
78 | const char *name) | 73 | const char *name) |
79 | { | 74 | { |
75 | struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); | ||
80 | struct rproc *rproc = vdev_to_rproc(vdev); | 76 | struct rproc *rproc = vdev_to_rproc(vdev); |
81 | struct rproc_vdev *rvdev = rproc->rvdev; | 77 | struct rproc_vring *rvring; |
82 | struct rproc_virtio_vq_info *rpvq; | ||
83 | struct virtqueue *vq; | 78 | struct virtqueue *vq; |
84 | void *addr; | 79 | void *addr; |
85 | int ret, len; | 80 | int len, size; |
86 | 81 | ||
87 | rpvq = kmalloc(sizeof(*rpvq), GFP_KERNEL); | 82 | /* we're temporarily limited to two virtqueues per rvdev */ |
88 | if (!rpvq) | 83 | if (id >= ARRAY_SIZE(rvdev->vring)) |
89 | return ERR_PTR(-ENOMEM); | 84 | return ERR_PTR(-EINVAL); |
85 | |||
86 | rvring = &rvdev->vring[id]; | ||
90 | 87 | ||
91 | rpvq->rproc = rproc; | 88 | addr = rvring->va; |
92 | rpvq->vq_id = id; | 89 | len = rvring->len; |
93 | 90 | ||
94 | addr = rvdev->vring[id].va; | 91 | /* zero vring */ |
95 | len = rvdev->vring[id].len; | 92 | size = vring_size(len, rvring->align); |
93 | memset(addr, 0, size); | ||
96 | 94 | ||
97 | dev_dbg(rproc->dev, "vring%d: va %p qsz %d\n", id, addr, len); | 95 | dev_dbg(rproc->dev, "vring%d: va %p qsz %d notifyid %d\n", |
96 | id, addr, len, rvring->notifyid); | ||
98 | 97 | ||
99 | /* | 98 | /* |
100 | * Create the new vq, and tell virtio we're not interested in | 99 | * Create the new vq, and tell virtio we're not interested in |
101 | * the 'weak' smp barriers, since we're talking with a real device. | 100 | * the 'weak' smp barriers, since we're talking with a real device. |
102 | */ | 101 | */ |
103 | vq = vring_new_virtqueue(len, AMP_VRING_ALIGN, vdev, false, addr, | 102 | vq = vring_new_virtqueue(len, rvring->align, vdev, false, addr, |
104 | rproc_virtio_notify, callback, name); | 103 | rproc_virtio_notify, callback, name); |
105 | if (!vq) { | 104 | if (!vq) { |
106 | dev_err(rproc->dev, "vring_new_virtqueue %s failed\n", name); | 105 | dev_err(rproc->dev, "vring_new_virtqueue %s failed\n", name); |
107 | ret = -ENOMEM; | 106 | return ERR_PTR(-ENOMEM); |
108 | goto free_rpvq; | ||
109 | } | 107 | } |
110 | 108 | ||
111 | rvdev->vq[id] = vq; | 109 | rvring->vq = vq; |
112 | vq->priv = rpvq; | 110 | vq->priv = rvring; |
113 | 111 | ||
114 | return vq; | 112 | return vq; |
115 | |||
116 | free_rpvq: | ||
117 | kfree(rpvq); | ||
118 | return ERR_PTR(ret); | ||
119 | } | 113 | } |
120 | 114 | ||
121 | static void rproc_virtio_del_vqs(struct virtio_device *vdev) | 115 | static void rproc_virtio_del_vqs(struct virtio_device *vdev) |
122 | { | 116 | { |
123 | struct virtqueue *vq, *n; | 117 | struct virtqueue *vq, *n; |
124 | struct rproc *rproc = vdev_to_rproc(vdev); | 118 | struct rproc *rproc = vdev_to_rproc(vdev); |
119 | struct rproc_vring *rvring; | ||
120 | |||
121 | /* power down the remote processor before deleting vqs */ | ||
122 | rproc_shutdown(rproc); | ||
125 | 123 | ||
126 | list_for_each_entry_safe(vq, n, &vdev->vqs, list) { | 124 | list_for_each_entry_safe(vq, n, &vdev->vqs, list) { |
127 | struct rproc_virtio_vq_info *rpvq = vq->priv; | 125 | rvring = vq->priv; |
126 | rvring->vq = NULL; | ||
128 | vring_del_virtqueue(vq); | 127 | vring_del_virtqueue(vq); |
129 | kfree(rpvq); | ||
130 | } | 128 | } |
131 | |||
132 | /* power down the remote processor */ | ||
133 | rproc_shutdown(rproc); | ||
134 | } | 129 | } |
135 | 130 | ||
136 | static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs, | 131 | static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs, |
@@ -141,17 +136,6 @@ static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs, | |||
141 | struct rproc *rproc = vdev_to_rproc(vdev); | 136 | struct rproc *rproc = vdev_to_rproc(vdev); |
142 | int i, ret; | 137 | int i, ret; |
143 | 138 | ||
144 | /* we maintain two virtqueues per remote processor (for RX and TX) */ | ||
145 | if (nvqs != 2) | ||
146 | return -EINVAL; | ||
147 | |||
148 | /* boot the remote processor */ | ||
149 | ret = rproc_boot(rproc); | ||
150 | if (ret) { | ||
151 | dev_err(rproc->dev, "rproc_boot() failed %d\n", ret); | ||
152 | goto error; | ||
153 | } | ||
154 | |||
155 | for (i = 0; i < nvqs; ++i) { | 139 | for (i = 0; i < nvqs; ++i) { |
156 | vqs[i] = rp_find_vq(vdev, i, callbacks[i], names[i]); | 140 | vqs[i] = rp_find_vq(vdev, i, callbacks[i], names[i]); |
157 | if (IS_ERR(vqs[i])) { | 141 | if (IS_ERR(vqs[i])) { |
@@ -160,6 +144,13 @@ static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs, | |||
160 | } | 144 | } |
161 | } | 145 | } |
162 | 146 | ||
147 | /* now that the vqs are all set, boot the remote processor */ | ||
148 | ret = rproc_boot(rproc); | ||
149 | if (ret) { | ||
150 | dev_err(rproc->dev, "rproc_boot() failed %d\n", ret); | ||
151 | goto error; | ||
152 | } | ||
153 | |||
163 | return 0; | 154 | return 0; |
164 | 155 | ||
165 | error: | 156 | error: |
@@ -170,7 +161,7 @@ error: | |||
170 | /* | 161 | /* |
171 | * We don't support yet real virtio status semantics. | 162 | * We don't support yet real virtio status semantics. |
172 | * | 163 | * |
173 | * The plan is to provide this via the VIRTIO HDR resource entry | 164 | * The plan is to provide this via the VDEV resource entry |
174 | * which is part of the firmware: this way the remote processor | 165 | * which is part of the firmware: this way the remote processor |
175 | * will be able to access the status values as set by us. | 166 | * will be able to access the status values as set by us. |
176 | */ | 167 | */ |
@@ -181,7 +172,7 @@ static u8 rproc_virtio_get_status(struct virtio_device *vdev) | |||
181 | 172 | ||
182 | static void rproc_virtio_set_status(struct virtio_device *vdev, u8 status) | 173 | static void rproc_virtio_set_status(struct virtio_device *vdev, u8 status) |
183 | { | 174 | { |
184 | dev_dbg(&vdev->dev, "new status: %d\n", status); | 175 | dev_dbg(&vdev->dev, "status: %d\n", status); |
185 | } | 176 | } |
186 | 177 | ||
187 | static void rproc_virtio_reset(struct virtio_device *vdev) | 178 | static void rproc_virtio_reset(struct virtio_device *vdev) |
@@ -192,15 +183,14 @@ static void rproc_virtio_reset(struct virtio_device *vdev) | |||
192 | /* provide the vdev features as retrieved from the firmware */ | 183 | /* provide the vdev features as retrieved from the firmware */ |
193 | static u32 rproc_virtio_get_features(struct virtio_device *vdev) | 184 | static u32 rproc_virtio_get_features(struct virtio_device *vdev) |
194 | { | 185 | { |
195 | struct rproc *rproc = vdev_to_rproc(vdev); | 186 | struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); |
196 | 187 | ||
197 | /* we only support a single vdev device for now */ | 188 | return rvdev->dfeatures; |
198 | return rproc->rvdev->dfeatures; | ||
199 | } | 189 | } |
200 | 190 | ||
201 | static void rproc_virtio_finalize_features(struct virtio_device *vdev) | 191 | static void rproc_virtio_finalize_features(struct virtio_device *vdev) |
202 | { | 192 | { |
203 | struct rproc *rproc = vdev_to_rproc(vdev); | 193 | struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); |
204 | 194 | ||
205 | /* Give virtio_ring a chance to accept features */ | 195 | /* Give virtio_ring a chance to accept features */ |
206 | vring_transport_features(vdev); | 196 | vring_transport_features(vdev); |
@@ -214,7 +204,7 @@ static void rproc_virtio_finalize_features(struct virtio_device *vdev) | |||
214 | * fixed as part of a small resource table overhaul and then an | 204 | * fixed as part of a small resource table overhaul and then an |
215 | * extension of the virtio resource entries. | 205 | * extension of the virtio resource entries. |
216 | */ | 206 | */ |
217 | rproc->rvdev->gfeatures = vdev->features[0]; | 207 | rvdev->gfeatures = vdev->features[0]; |
218 | } | 208 | } |
219 | 209 | ||
220 | static struct virtio_config_ops rproc_virtio_config_ops = { | 210 | static struct virtio_config_ops rproc_virtio_config_ops = { |
@@ -244,26 +234,25 @@ static void rproc_vdev_release(struct device *dev) | |||
244 | } | 234 | } |
245 | 235 | ||
246 | /** | 236 | /** |
247 | * rproc_add_rpmsg_vdev() - create an rpmsg virtio device | 237 | * rproc_add_virtio_dev() - register an rproc-induced virtio device |
248 | * @rproc: the rproc handle | 238 | * @rvdev: the remote vdev |
249 | * | 239 | * |
250 | * This function is called if virtio rpmsg support was found in the | 240 | * This function registers a virtio device. This vdev's partent is |
251 | * firmware of the remote processor. | 241 | * the rproc device. |
252 | * | 242 | * |
253 | * Today we only support creating a single rpmsg vdev (virtio device), | 243 | * Returns 0 on success or an appropriate error value otherwise. |
254 | * but the plan is to remove this limitation. At that point this interface | ||
255 | * will be revised/extended. | ||
256 | */ | 244 | */ |
257 | int rproc_add_rpmsg_vdev(struct rproc *rproc) | 245 | int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id) |
258 | { | 246 | { |
247 | struct rproc *rproc = rvdev->rproc; | ||
259 | struct device *dev = rproc->dev; | 248 | struct device *dev = rproc->dev; |
260 | struct rproc_vdev *rvdev = rproc->rvdev; | 249 | struct virtio_device *vdev = &rvdev->vdev; |
261 | int ret; | 250 | int ret; |
262 | 251 | ||
263 | rvdev->vdev.id.device = VIRTIO_ID_RPMSG, | 252 | vdev->id.device = id, |
264 | rvdev->vdev.config = &rproc_virtio_config_ops, | 253 | vdev->config = &rproc_virtio_config_ops, |
265 | rvdev->vdev.dev.parent = dev; | 254 | vdev->dev.parent = dev; |
266 | rvdev->vdev.dev.release = rproc_vdev_release; | 255 | vdev->dev.release = rproc_vdev_release; |
267 | 256 | ||
268 | /* | 257 | /* |
269 | * We're indirectly making a non-temporary copy of the rproc pointer | 258 | * We're indirectly making a non-temporary copy of the rproc pointer |
@@ -275,25 +264,26 @@ int rproc_add_rpmsg_vdev(struct rproc *rproc) | |||
275 | */ | 264 | */ |
276 | kref_get(&rproc->refcount); | 265 | kref_get(&rproc->refcount); |
277 | 266 | ||
278 | ret = register_virtio_device(&rvdev->vdev); | 267 | ret = register_virtio_device(vdev); |
279 | if (ret) { | 268 | if (ret) { |
280 | kref_put(&rproc->refcount, rproc_release); | 269 | kref_put(&rproc->refcount, rproc_release); |
281 | dev_err(dev, "failed to register vdev: %d\n", ret); | 270 | dev_err(dev, "failed to register vdev: %d\n", ret); |
271 | goto out; | ||
282 | } | 272 | } |
283 | 273 | ||
274 | dev_info(dev, "registered %s (type %d)\n", dev_name(&vdev->dev), id); | ||
275 | |||
276 | out: | ||
284 | return ret; | 277 | return ret; |
285 | } | 278 | } |
286 | 279 | ||
287 | /** | 280 | /** |
288 | * rproc_remove_rpmsg_vdev() - remove an rpmsg vdev device | 281 | * rproc_remove_virtio_dev() - remove an rproc-induced virtio device |
289 | * @rproc: the rproc handle | 282 | * @rvdev: the remote vdev |
290 | * | 283 | * |
291 | * This function is called whenever @rproc is removed _iff_ an rpmsg | 284 | * This function unregisters an existing virtio device. |
292 | * vdev was created beforehand. | ||
293 | */ | 285 | */ |
294 | void rproc_remove_rpmsg_vdev(struct rproc *rproc) | 286 | void rproc_remove_virtio_dev(struct rproc_vdev *rvdev) |
295 | { | 287 | { |
296 | struct rproc_vdev *rvdev = rproc->rvdev; | ||
297 | |||
298 | unregister_virtio_device(&rvdev->vdev); | 288 | unregister_virtio_device(&rvdev->vdev); |
299 | } | 289 | } |
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c index 8980ac2cc546..75506ec2840e 100644 --- a/drivers/rpmsg/virtio_rpmsg_bus.c +++ b/drivers/rpmsg/virtio_rpmsg_bus.c | |||
@@ -290,22 +290,36 @@ struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_channel *rpdev, | |||
290 | EXPORT_SYMBOL(rpmsg_create_ept); | 290 | EXPORT_SYMBOL(rpmsg_create_ept); |
291 | 291 | ||
292 | /** | 292 | /** |
293 | * rpmsg_destroy_ept() - destroy an existing rpmsg endpoint | 293 | * __rpmsg_destroy_ept() - destroy an existing rpmsg endpoint |
294 | * @vrp: virtproc which owns this ept | ||
294 | * @ept: endpoing to destroy | 295 | * @ept: endpoing to destroy |
295 | * | 296 | * |
296 | * Should be used by drivers to destroy an rpmsg endpoint previously | 297 | * An internal function which destroy an ept without assuming it is |
297 | * created with rpmsg_create_ept(). | 298 | * bound to an rpmsg channel. This is needed for handling the internal |
299 | * name service endpoint, which isn't bound to an rpmsg channel. | ||
300 | * See also __rpmsg_create_ept(). | ||
298 | */ | 301 | */ |
299 | void rpmsg_destroy_ept(struct rpmsg_endpoint *ept) | 302 | static void |
303 | __rpmsg_destroy_ept(struct virtproc_info *vrp, struct rpmsg_endpoint *ept) | ||
300 | { | 304 | { |
301 | struct virtproc_info *vrp = ept->rpdev->vrp; | ||
302 | |||
303 | mutex_lock(&vrp->endpoints_lock); | 305 | mutex_lock(&vrp->endpoints_lock); |
304 | idr_remove(&vrp->endpoints, ept->addr); | 306 | idr_remove(&vrp->endpoints, ept->addr); |
305 | mutex_unlock(&vrp->endpoints_lock); | 307 | mutex_unlock(&vrp->endpoints_lock); |
306 | 308 | ||
307 | kfree(ept); | 309 | kfree(ept); |
308 | } | 310 | } |
311 | |||
312 | /** | ||
313 | * rpmsg_destroy_ept() - destroy an existing rpmsg endpoint | ||
314 | * @ept: endpoing to destroy | ||
315 | * | ||
316 | * Should be used by drivers to destroy an rpmsg endpoint previously | ||
317 | * created with rpmsg_create_ept(). | ||
318 | */ | ||
319 | void rpmsg_destroy_ept(struct rpmsg_endpoint *ept) | ||
320 | { | ||
321 | __rpmsg_destroy_ept(ept->rpdev->vrp, ept); | ||
322 | } | ||
309 | EXPORT_SYMBOL(rpmsg_destroy_ept); | 323 | EXPORT_SYMBOL(rpmsg_destroy_ept); |
310 | 324 | ||
311 | /* | 325 | /* |
@@ -764,6 +778,16 @@ static void rpmsg_recv_done(struct virtqueue *rvq) | |||
764 | print_hex_dump(KERN_DEBUG, "rpmsg_virtio RX: ", DUMP_PREFIX_NONE, 16, 1, | 778 | print_hex_dump(KERN_DEBUG, "rpmsg_virtio RX: ", DUMP_PREFIX_NONE, 16, 1, |
765 | msg, sizeof(*msg) + msg->len, true); | 779 | msg, sizeof(*msg) + msg->len, true); |
766 | 780 | ||
781 | /* | ||
782 | * We currently use fixed-sized buffers, so trivially sanitize | ||
783 | * the reported payload length. | ||
784 | */ | ||
785 | if (len > RPMSG_BUF_SIZE || | ||
786 | msg->len > (len - sizeof(struct rpmsg_hdr))) { | ||
787 | dev_warn(dev, "inbound msg too big: (%d, %d)\n", len, msg->len); | ||
788 | return; | ||
789 | } | ||
790 | |||
767 | /* use the dst addr to fetch the callback of the appropriate user */ | 791 | /* use the dst addr to fetch the callback of the appropriate user */ |
768 | mutex_lock(&vrp->endpoints_lock); | 792 | mutex_lock(&vrp->endpoints_lock); |
769 | ept = idr_find(&vrp->endpoints, msg->dst); | 793 | ept = idr_find(&vrp->endpoints, msg->dst); |
@@ -774,7 +798,8 @@ static void rpmsg_recv_done(struct virtqueue *rvq) | |||
774 | else | 798 | else |
775 | dev_warn(dev, "msg received with no recepient\n"); | 799 | dev_warn(dev, "msg received with no recepient\n"); |
776 | 800 | ||
777 | sg_init_one(&sg, msg, sizeof(*msg) + len); | 801 | /* publish the real size of the buffer */ |
802 | sg_init_one(&sg, msg, RPMSG_BUF_SIZE); | ||
778 | 803 | ||
779 | /* add the buffer back to the remote processor's virtqueue */ | 804 | /* add the buffer back to the remote processor's virtqueue */ |
780 | err = virtqueue_add_buf(vrp->rvq, &sg, 0, 1, msg, GFP_KERNEL); | 805 | err = virtqueue_add_buf(vrp->rvq, &sg, 0, 1, msg, GFP_KERNEL); |
@@ -891,8 +916,8 @@ static int rpmsg_probe(struct virtio_device *vdev) | |||
891 | if (!bufs_va) | 916 | if (!bufs_va) |
892 | goto vqs_del; | 917 | goto vqs_del; |
893 | 918 | ||
894 | dev_dbg(&vdev->dev, "buffers: va %p, dma 0x%x\n", bufs_va, | 919 | dev_dbg(&vdev->dev, "buffers: va %p, dma 0x%llx\n", bufs_va, |
895 | vrp->bufs_dma); | 920 | (unsigned long long)vrp->bufs_dma); |
896 | 921 | ||
897 | /* half of the buffers is dedicated for RX */ | 922 | /* half of the buffers is dedicated for RX */ |
898 | vrp->rbufs = bufs_va; | 923 | vrp->rbufs = bufs_va; |
@@ -964,6 +989,9 @@ static void __devexit rpmsg_remove(struct virtio_device *vdev) | |||
964 | if (ret) | 989 | if (ret) |
965 | dev_warn(&vdev->dev, "can't remove rpmsg device: %d\n", ret); | 990 | dev_warn(&vdev->dev, "can't remove rpmsg device: %d\n", ret); |
966 | 991 | ||
992 | if (vrp->ns_ept) | ||
993 | __rpmsg_destroy_ept(vrp, vrp->ns_ept); | ||
994 | |||
967 | idr_remove_all(&vrp->endpoints); | 995 | idr_remove_all(&vrp->endpoints); |
968 | idr_destroy(&vrp->endpoints); | 996 | idr_destroy(&vrp->endpoints); |
969 | 997 | ||
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h index ada4cb063dfe..f1ffabb978d3 100644 --- a/include/linux/remoteproc.h +++ b/include/linux/remoteproc.h | |||
@@ -41,48 +41,54 @@ | |||
41 | #include <linux/mutex.h> | 41 | #include <linux/mutex.h> |
42 | #include <linux/virtio.h> | 42 | #include <linux/virtio.h> |
43 | #include <linux/completion.h> | 43 | #include <linux/completion.h> |
44 | 44 | #include <linux/idr.h> | |
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 | 45 | ||
52 | /** | 46 | /** |
53 | * struct fw_resource - describes an entry from the resource section | 47 | * struct resource_table - firmware resource table header |
54 | * @type: resource type | 48 | * @ver: version number |
55 | * @id: index number of the resource | 49 | * @num: number of resource entries |
56 | * @da: device address of the resource | 50 | * @reserved: reserved (must be zero) |
57 | * @pa: physical address of the resource | 51 | * @offset: array of offsets pointing at the various resource entries |
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 | * | 52 | * |
63 | * The remote processor firmware should contain a "resource table": | 53 | * A resource table is essentially a list of system resources required |
64 | * array of 'struct fw_resource' entries. | 54 | * by the remote processor. It may also include configuration entries. |
55 | * If needed, the remote processor firmware should contain this table | ||
56 | * as a dedicated ".resource_table" ELF section. | ||
65 | * | 57 | * |
66 | * Some resources entries are mere announcements, where the host is informed | 58 | * Some resources entries are mere announcements, where the host is informed |
67 | * of specific remoteproc configuration. Other entries require the host to | 59 | * of specific remoteproc configuration. Other entries require the host to |
68 | * do something (e.g. reserve a requested resource) and possibly also reply | 60 | * do something (e.g. allocate a system resource). Sometimes a negotiation |
69 | * by overwriting a member inside 'struct fw_resource' with info about the | 61 | * is expected, where the firmware requests a resource, and once allocated, |
70 | * allocated resource. | 62 | * the host should provide back its details (e.g. address of an allocated |
71 | * | 63 | * memory region). |
72 | * Different resource entries use different members of this struct, | 64 | * |
73 | * with different meanings. This is pretty limiting and error-prone, | 65 | * The header of the resource table, as expressed by this structure, |
74 | * so the plan is to move to variable-length TLV-based resource entries, | 66 | * contains a version number (should we need to change this format in the |
75 | * where each resource type will have its own structure. | 67 | * future), the number of available resource entries, and their offsets |
68 | * in the table. | ||
69 | * | ||
70 | * Immediately following this header are the resource entries themselves, | ||
71 | * each of which begins with a resource entry header (as described below). | ||
76 | */ | 72 | */ |
77 | struct fw_resource { | 73 | struct resource_table { |
74 | u32 ver; | ||
75 | u32 num; | ||
76 | u32 reserved[2]; | ||
77 | u32 offset[0]; | ||
78 | } __packed; | ||
79 | |||
80 | /** | ||
81 | * struct fw_rsc_hdr - firmware resource entry header | ||
82 | * @type: resource type | ||
83 | * @data: resource data | ||
84 | * | ||
85 | * Every resource entry begins with a 'struct fw_rsc_hdr' header providing | ||
86 | * its @type. The content of the entry itself will immediately follow | ||
87 | * this header, and it should be parsed according to the resource type. | ||
88 | */ | ||
89 | struct fw_rsc_hdr { | ||
78 | u32 type; | 90 | u32 type; |
79 | u32 id; | 91 | u8 data[0]; |
80 | u64 da; | ||
81 | u64 pa; | ||
82 | u32 len; | ||
83 | u32 flags; | ||
84 | u8 reserved[16]; | ||
85 | u8 name[48]; | ||
86 | } __packed; | 92 | } __packed; |
87 | 93 | ||
88 | /** | 94 | /** |
@@ -92,30 +98,13 @@ struct fw_resource { | |||
92 | * memory region. | 98 | * memory region. |
93 | * @RSC_DEVMEM: request to iommu_map a memory-based peripheral. | 99 | * @RSC_DEVMEM: request to iommu_map a memory-based peripheral. |
94 | * @RSC_TRACE: announces the availability of a trace buffer into which | 100 | * @RSC_TRACE: announces the availability of a trace buffer into which |
95 | * the remote processor will be writing logs. In this case, | 101 | * the remote processor will be writing logs. |
96 | * 'da' indicates the device address where logs are written to, | 102 | * @RSC_VDEV: declare support for a virtio device, and serve as its |
97 | * and 'len' is the size of the trace buffer. | 103 | * virtio header. |
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 | * @RSC_LAST: just keep this one at the end | 104 | * @RSC_LAST: just keep this one at the end |
107 | * | 105 | * |
108 | * Most of the resource entries share the basic idea of address/length | 106 | * For more details regarding a specific resource type, please see its |
109 | * negotiation with the host: the firmware usually asks (on behalf of the | 107 | * dedicated structure below. |
110 | * remote processor that will soon be booted with it) for memory | ||
111 | * of size 'len' bytes, and the host needs to allocate it and provide | ||
112 | * the device/physical address (when relevant) in 'da'/'pa' respectively. | ||
113 | * | ||
114 | * If the firmware is compiled with hard coded device addresses, and | ||
115 | * can't handle dynamically allocated 'da' values, then the 'da' field | ||
116 | * will contain the expected device addresses (today we actually only support | ||
117 | * this scheme, as there aren't yet any use cases for dynamically allocated | ||
118 | * device addresses). | ||
119 | * | 108 | * |
120 | * Please note that these values are used as indices to the rproc_handle_rsc | 109 | * Please note that these values are used as indices to the rproc_handle_rsc |
121 | * lookup table, so please keep them sane. Moreover, @RSC_LAST is used to | 110 | * lookup table, so please keep them sane. Moreover, @RSC_LAST is used to |
@@ -126,11 +115,197 @@ enum fw_resource_type { | |||
126 | RSC_CARVEOUT = 0, | 115 | RSC_CARVEOUT = 0, |
127 | RSC_DEVMEM = 1, | 116 | RSC_DEVMEM = 1, |
128 | RSC_TRACE = 2, | 117 | RSC_TRACE = 2, |
129 | RSC_VRING = 3, | 118 | RSC_VDEV = 3, |
130 | RSC_VIRTIO_DEV = 4, | 119 | RSC_LAST = 4, |
131 | RSC_LAST = 5, | ||
132 | }; | 120 | }; |
133 | 121 | ||
122 | #define FW_RSC_ADDR_ANY (0xFFFFFFFFFFFFFFFF) | ||
123 | |||
124 | /** | ||
125 | * struct fw_rsc_carveout - physically contiguous memory request | ||
126 | * @da: device address | ||
127 | * @pa: physical address | ||
128 | * @len: length (in bytes) | ||
129 | * @flags: iommu protection flags | ||
130 | * @reserved: reserved (must be zero) | ||
131 | * @name: human-readable name of the requested memory region | ||
132 | * | ||
133 | * This resource entry requests the host to allocate a physically contiguous | ||
134 | * memory region. | ||
135 | * | ||
136 | * These request entries should precede other firmware resource entries, | ||
137 | * as other entries might request placing other data objects inside | ||
138 | * these memory regions (e.g. data/code segments, trace resource entries, ...). | ||
139 | * | ||
140 | * Allocating memory this way helps utilizing the reserved physical memory | ||
141 | * (e.g. CMA) more efficiently, and also minimizes the number of TLB entries | ||
142 | * needed to map it (in case @rproc is using an IOMMU). Reducing the TLB | ||
143 | * pressure is important; it may have a substantial impact on performance. | ||
144 | * | ||
145 | * If the firmware is compiled with static addresses, then @da should specify | ||
146 | * the expected device address of this memory region. If @da is set to | ||
147 | * FW_RSC_ADDR_ANY, then the host will dynamically allocate it, and then | ||
148 | * overwrite @da with the dynamically allocated address. | ||
149 | * | ||
150 | * We will always use @da to negotiate the device addresses, even if it | ||
151 | * isn't using an iommu. In that case, though, it will obviously contain | ||
152 | * physical addresses. | ||
153 | * | ||
154 | * Some remote processors needs to know the allocated physical address | ||
155 | * even if they do use an iommu. This is needed, e.g., if they control | ||
156 | * hardware accelerators which access the physical memory directly (this | ||
157 | * is the case with OMAP4 for instance). In that case, the host will | ||
158 | * overwrite @pa with the dynamically allocated physical address. | ||
159 | * Generally we don't want to expose physical addresses if we don't have to | ||
160 | * (remote processors are generally _not_ trusted), so we might want to | ||
161 | * change this to happen _only_ when explicitly required by the hardware. | ||
162 | * | ||
163 | * @flags is used to provide IOMMU protection flags, and @name should | ||
164 | * (optionally) contain a human readable name of this carveout region | ||
165 | * (mainly for debugging purposes). | ||
166 | */ | ||
167 | struct fw_rsc_carveout { | ||
168 | u32 da; | ||
169 | u32 pa; | ||
170 | u32 len; | ||
171 | u32 flags; | ||
172 | u32 reserved; | ||
173 | u8 name[32]; | ||
174 | } __packed; | ||
175 | |||
176 | /** | ||
177 | * struct fw_rsc_devmem - iommu mapping request | ||
178 | * @da: device address | ||
179 | * @pa: physical address | ||
180 | * @len: length (in bytes) | ||
181 | * @flags: iommu protection flags | ||
182 | * @reserved: reserved (must be zero) | ||
183 | * @name: human-readable name of the requested region to be mapped | ||
184 | * | ||
185 | * This resource entry requests the host to iommu map a physically contiguous | ||
186 | * memory region. This is needed in case the remote processor requires | ||
187 | * access to certain memory-based peripherals; _never_ use it to access | ||
188 | * regular memory. | ||
189 | * | ||
190 | * This is obviously only needed if the remote processor is accessing memory | ||
191 | * via an iommu. | ||
192 | * | ||
193 | * @da should specify the required device address, @pa should specify | ||
194 | * the physical address we want to map, @len should specify the size of | ||
195 | * the mapping and @flags is the IOMMU protection flags. As always, @name may | ||
196 | * (optionally) contain a human readable name of this mapping (mainly for | ||
197 | * debugging purposes). | ||
198 | * | ||
199 | * Note: at this point we just "trust" those devmem entries to contain valid | ||
200 | * physical addresses, but this isn't safe and will be changed: eventually we | ||
201 | * want remoteproc implementations to provide us ranges of physical addresses | ||
202 | * the firmware is allowed to request, and not allow firmwares to request | ||
203 | * access to physical addresses that are outside those ranges. | ||
204 | */ | ||
205 | struct fw_rsc_devmem { | ||
206 | u32 da; | ||
207 | u32 pa; | ||
208 | u32 len; | ||
209 | u32 flags; | ||
210 | u32 reserved; | ||
211 | u8 name[32]; | ||
212 | } __packed; | ||
213 | |||
214 | /** | ||
215 | * struct fw_rsc_trace - trace buffer declaration | ||
216 | * @da: device address | ||
217 | * @len: length (in bytes) | ||
218 | * @reserved: reserved (must be zero) | ||
219 | * @name: human-readable name of the trace buffer | ||
220 | * | ||
221 | * This resource entry provides the host information about a trace buffer | ||
222 | * into which the remote processor will write log messages. | ||
223 | * | ||
224 | * @da specifies the device address of the buffer, @len specifies | ||
225 | * its size, and @name may contain a human readable name of the trace buffer. | ||
226 | * | ||
227 | * After booting the remote processor, the trace buffers are exposed to the | ||
228 | * user via debugfs entries (called trace0, trace1, etc..). | ||
229 | */ | ||
230 | struct fw_rsc_trace { | ||
231 | u32 da; | ||
232 | u32 len; | ||
233 | u32 reserved; | ||
234 | u8 name[32]; | ||
235 | } __packed; | ||
236 | |||
237 | /** | ||
238 | * struct fw_rsc_vdev_vring - vring descriptor entry | ||
239 | * @da: device address | ||
240 | * @align: the alignment between the consumer and producer parts of the vring | ||
241 | * @num: num of buffers supported by this vring (must be power of two) | ||
242 | * @notifyid is a unique rproc-wide notify index for this vring. This notify | ||
243 | * index is used when kicking a remote processor, to let it know that this | ||
244 | * vring is triggered. | ||
245 | * @reserved: reserved (must be zero) | ||
246 | * | ||
247 | * This descriptor is not a resource entry by itself; it is part of the | ||
248 | * vdev resource type (see below). | ||
249 | * | ||
250 | * Note that @da should either contain the device address where | ||
251 | * the remote processor is expecting the vring, or indicate that | ||
252 | * dynamically allocation of the vring's device address is supported. | ||
253 | */ | ||
254 | struct fw_rsc_vdev_vring { | ||
255 | u32 da; | ||
256 | u32 align; | ||
257 | u32 num; | ||
258 | u32 notifyid; | ||
259 | u32 reserved; | ||
260 | } __packed; | ||
261 | |||
262 | /** | ||
263 | * struct fw_rsc_vdev - virtio device header | ||
264 | * @id: virtio device id (as in virtio_ids.h) | ||
265 | * @notifyid is a unique rproc-wide notify index for this vdev. This notify | ||
266 | * index is used when kicking a remote processor, to let it know that the | ||
267 | * status/features of this vdev have changes. | ||
268 | * @dfeatures specifies the virtio device features supported by the firmware | ||
269 | * @gfeatures is a place holder used by the host to write back the | ||
270 | * negotiated features that are supported by both sides. | ||
271 | * @config_len is the size of the virtio config space of this vdev. The config | ||
272 | * space lies in the resource table immediate after this vdev header. | ||
273 | * @status is a place holder where the host will indicate its virtio progress. | ||
274 | * @num_of_vrings indicates how many vrings are described in this vdev header | ||
275 | * @reserved: reserved (must be zero) | ||
276 | * @vring is an array of @num_of_vrings entries of 'struct fw_rsc_vdev_vring'. | ||
277 | * | ||
278 | * This resource is a virtio device header: it provides information about | ||
279 | * the vdev, and is then used by the host and its peer remote processors | ||
280 | * to negotiate and share certain virtio properties. | ||
281 | * | ||
282 | * By providing this resource entry, the firmware essentially asks remoteproc | ||
283 | * to statically allocate a vdev upon registration of the rproc (dynamic vdev | ||
284 | * allocation is not yet supported). | ||
285 | * | ||
286 | * Note: unlike virtualization systems, the term 'host' here means | ||
287 | * the Linux side which is running remoteproc to control the remote | ||
288 | * processors. We use the name 'gfeatures' to comply with virtio's terms, | ||
289 | * though there isn't really any virtualized guest OS here: it's the host | ||
290 | * which is responsible for negotiating the final features. | ||
291 | * Yeah, it's a bit confusing. | ||
292 | * | ||
293 | * Note: immediately following this structure is the virtio config space for | ||
294 | * this vdev (which is specific to the vdev; for more info, read the virtio | ||
295 | * spec). the size of the config space is specified by @config_len. | ||
296 | */ | ||
297 | struct fw_rsc_vdev { | ||
298 | u32 id; | ||
299 | u32 notifyid; | ||
300 | u32 dfeatures; | ||
301 | u32 gfeatures; | ||
302 | u32 config_len; | ||
303 | u8 status; | ||
304 | u8 num_of_vrings; | ||
305 | u8 reserved[2]; | ||
306 | struct fw_rsc_vdev_vring vring[0]; | ||
307 | } __packed; | ||
308 | |||
134 | /** | 309 | /** |
135 | * struct rproc_mem_entry - memory entry descriptor | 310 | * struct rproc_mem_entry - memory entry descriptor |
136 | * @va: virtual address | 311 | * @va: virtual address |
@@ -144,7 +319,7 @@ struct rproc_mem_entry { | |||
144 | void *va; | 319 | void *va; |
145 | dma_addr_t dma; | 320 | dma_addr_t dma; |
146 | int len; | 321 | int len; |
147 | u64 da; | 322 | u32 da; |
148 | void *priv; | 323 | void *priv; |
149 | struct list_head node; | 324 | struct list_head node; |
150 | }; | 325 | }; |
@@ -206,7 +381,8 @@ enum rproc_state { | |||
206 | * @mappings: list of iommu mappings we initiated, needed on shutdown | 381 | * @mappings: list of iommu mappings we initiated, needed on shutdown |
207 | * @firmware_loading_complete: marks e/o asynchronous firmware loading | 382 | * @firmware_loading_complete: marks e/o asynchronous firmware loading |
208 | * @bootaddr: address of first instruction to boot rproc with (optional) | 383 | * @bootaddr: address of first instruction to boot rproc with (optional) |
209 | * @rvdev: virtio device (we only support a single rpmsg virtio device for now) | 384 | * @rvdevs: list of remote virtio devices |
385 | * @notifyids: idr for dynamically assigning rproc-wide unique notify ids | ||
210 | */ | 386 | */ |
211 | struct rproc { | 387 | struct rproc { |
212 | struct klist_node node; | 388 | struct klist_node node; |
@@ -226,24 +402,50 @@ struct rproc { | |||
226 | struct list_head carveouts; | 402 | struct list_head carveouts; |
227 | struct list_head mappings; | 403 | struct list_head mappings; |
228 | struct completion firmware_loading_complete; | 404 | struct completion firmware_loading_complete; |
229 | u64 bootaddr; | 405 | u32 bootaddr; |
406 | struct list_head rvdevs; | ||
407 | struct idr notifyids; | ||
408 | }; | ||
409 | |||
410 | /* we currently support only two vrings per rvdev */ | ||
411 | #define RVDEV_NUM_VRINGS 2 | ||
412 | |||
413 | /** | ||
414 | * struct rproc_vring - remoteproc vring state | ||
415 | * @va: virtual address | ||
416 | * @dma: dma address | ||
417 | * @len: length, in bytes | ||
418 | * @da: device address | ||
419 | * @align: vring alignment | ||
420 | * @notifyid: rproc-specific unique vring index | ||
421 | * @rvdev: remote vdev | ||
422 | * @vq: the virtqueue of this vring | ||
423 | */ | ||
424 | struct rproc_vring { | ||
425 | void *va; | ||
426 | dma_addr_t dma; | ||
427 | int len; | ||
428 | u32 da; | ||
429 | u32 align; | ||
430 | int notifyid; | ||
230 | struct rproc_vdev *rvdev; | 431 | struct rproc_vdev *rvdev; |
432 | struct virtqueue *vq; | ||
231 | }; | 433 | }; |
232 | 434 | ||
233 | /** | 435 | /** |
234 | * struct rproc_vdev - remoteproc state for a supported virtio device | 436 | * struct rproc_vdev - remoteproc state for a supported virtio device |
437 | * @node: list node | ||
235 | * @rproc: the rproc handle | 438 | * @rproc: the rproc handle |
236 | * @vdev: the virio device | 439 | * @vdev: the virio device |
237 | * @vq: the virtqueues for this vdev | ||
238 | * @vring: the vrings for this vdev | 440 | * @vring: the vrings for this vdev |
239 | * @dfeatures: virtio device features | 441 | * @dfeatures: virtio device features |
240 | * @gfeatures: virtio guest features | 442 | * @gfeatures: virtio guest features |
241 | */ | 443 | */ |
242 | struct rproc_vdev { | 444 | struct rproc_vdev { |
445 | struct list_head node; | ||
243 | struct rproc *rproc; | 446 | struct rproc *rproc; |
244 | struct virtio_device vdev; | 447 | struct virtio_device vdev; |
245 | struct virtqueue *vq[2]; | 448 | struct rproc_vring vring[RVDEV_NUM_VRINGS]; |
246 | struct rproc_mem_entry vring[2]; | ||
247 | unsigned long dfeatures; | 449 | unsigned long dfeatures; |
248 | unsigned long gfeatures; | 450 | unsigned long gfeatures; |
249 | }; | 451 | }; |
@@ -261,9 +463,14 @@ int rproc_unregister(struct rproc *rproc); | |||
261 | int rproc_boot(struct rproc *rproc); | 463 | int rproc_boot(struct rproc *rproc); |
262 | void rproc_shutdown(struct rproc *rproc); | 464 | void rproc_shutdown(struct rproc *rproc); |
263 | 465 | ||
466 | static inline struct rproc_vdev *vdev_to_rvdev(struct virtio_device *vdev) | ||
467 | { | ||
468 | return container_of(vdev, struct rproc_vdev, vdev); | ||
469 | } | ||
470 | |||
264 | static inline struct rproc *vdev_to_rproc(struct virtio_device *vdev) | 471 | static inline struct rproc *vdev_to_rproc(struct virtio_device *vdev) |
265 | { | 472 | { |
266 | struct rproc_vdev *rvdev = container_of(vdev, struct rproc_vdev, vdev); | 473 | struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); |
267 | 474 | ||
268 | return rvdev->rproc; | 475 | return rvdev->rproc; |
269 | } | 476 | } |