aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/remoteproc/remoteproc_core.c109
-rw-r--r--drivers/remoteproc/remoteproc_internal.h2
-rw-r--r--drivers/remoteproc/remoteproc_virtio.c13
3 files changed, 67 insertions, 57 deletions
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index 8ea7bccc7100..288d4175bbf6 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -279,34 +279,17 @@ rproc_load_segments(struct rproc *rproc, const u8 *elf_data, size_t len)
279 return ret; 279 return ret;
280} 280}
281 281
282static int 282int rproc_alloc_vring(struct rproc_vdev *rvdev, int i)
283__rproc_handle_vring(struct rproc_vdev *rvdev, struct fw_rsc_vdev *rsc, int i)
284{ 283{
285 struct rproc *rproc = rvdev->rproc; 284 struct rproc *rproc = rvdev->rproc;
286 struct device *dev = rproc->dev; 285 struct device *dev = rproc->dev;
287 struct fw_rsc_vdev_vring *vring = &rsc->vring[i]; 286 struct rproc_vring *rvring = &rvdev->vring[i];
288 dma_addr_t dma; 287 dma_addr_t dma;
289 void *va; 288 void *va;
290 int ret, size, notifyid; 289 int ret, size, notifyid;
291 290
292 dev_dbg(dev, "vdev rsc: vring%d: da %x, qsz %d, align %d\n",
293 i, vring->da, vring->num, vring->align);
294
295 /* make sure reserved bytes are zeroes */
296 if (vring->reserved) {
297 dev_err(dev, "vring rsc has non zero reserved bytes\n");
298 return -EINVAL;
299 }
300
301 /* verify queue size and vring alignment are sane */
302 if (!vring->num || !vring->align) {
303 dev_err(dev, "invalid qsz (%d) or alignment (%d)\n",
304 vring->num, vring->align);
305 return -EINVAL;
306 }
307
308 /* actual size of vring (in bytes) */ 291 /* actual size of vring (in bytes) */
309 size = PAGE_ALIGN(vring_size(vring->num, vring->align)); 292 size = PAGE_ALIGN(vring_size(rvring->len, rvring->align));
310 293
311 if (!idr_pre_get(&rproc->notifyids, GFP_KERNEL)) { 294 if (!idr_pre_get(&rproc->notifyids, GFP_KERNEL)) {
312 dev_err(dev, "idr_pre_get failed\n"); 295 dev_err(dev, "idr_pre_get failed\n");
@@ -316,6 +299,7 @@ __rproc_handle_vring(struct rproc_vdev *rvdev, struct fw_rsc_vdev *rsc, int i)
316 /* 299 /*
317 * Allocate non-cacheable memory for the vring. In the future 300 * Allocate non-cacheable memory for the vring. In the future
318 * this call will also configure the IOMMU for us 301 * this call will also configure the IOMMU for us
302 * TODO: let the rproc know the da of this vring
319 */ 303 */
320 va = dma_alloc_coherent(dev, size, &dma, GFP_KERNEL); 304 va = dma_alloc_coherent(dev, size, &dma, GFP_KERNEL);
321 if (!va) { 305 if (!va) {
@@ -323,44 +307,67 @@ __rproc_handle_vring(struct rproc_vdev *rvdev, struct fw_rsc_vdev *rsc, int i)
323 return -EINVAL; 307 return -EINVAL;
324 } 308 }
325 309
326 /* assign an rproc-wide unique index for this vring */ 310 /*
327 /* TODO: assign a notifyid for rvdev updates as well */ 311 * Assign an rproc-wide unique index for this vring
328 ret = idr_get_new(&rproc->notifyids, &rvdev->vring[i], &notifyid); 312 * TODO: assign a notifyid for rvdev updates as well
313 * TODO: let the rproc know the notifyid of this vring
314 * TODO: support predefined notifyids (via resource table)
315 */
316 ret = idr_get_new(&rproc->notifyids, rvring, &notifyid);
329 if (ret) { 317 if (ret) {
330 dev_err(dev, "idr_get_new failed: %d\n", ret); 318 dev_err(dev, "idr_get_new failed: %d\n", ret);
331 dma_free_coherent(dev, size, va, dma); 319 dma_free_coherent(dev, size, va, dma);
332 return ret; 320 return ret;
333 } 321 }
334 322
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, 323 dev_dbg(dev, "vring%d: va %p dma %x size %x idr %d\n", i, va,
341 dma, size, notifyid); 324 dma, size, notifyid);
342 325
343 rvdev->vring[i].len = vring->num; 326 rvring->va = va;
344 rvdev->vring[i].align = vring->align; 327 rvring->dma = dma;
345 rvdev->vring[i].va = va; 328 rvring->notifyid = notifyid;
346 rvdev->vring[i].dma = dma;
347 rvdev->vring[i].notifyid = notifyid;
348 rvdev->vring[i].rvdev = rvdev;
349 329
350 return 0; 330 return 0;
351} 331}
352 332
353static void __rproc_free_vrings(struct rproc_vdev *rvdev, int i) 333static int
334rproc_parse_vring(struct rproc_vdev *rvdev, struct fw_rsc_vdev *rsc, int i)
354{ 335{
355 struct rproc *rproc = rvdev->rproc; 336 struct rproc *rproc = rvdev->rproc;
337 struct device *dev = rproc->dev;
338 struct fw_rsc_vdev_vring *vring = &rsc->vring[i];
339 struct rproc_vring *rvring = &rvdev->vring[i];
356 340
357 for (i--; i >= 0; i--) { 341 dev_dbg(dev, "vdev rsc: vring%d: da %x, qsz %d, align %d\n",
358 struct rproc_vring *rvring = &rvdev->vring[i]; 342 i, vring->da, vring->num, vring->align);
359 int size = PAGE_ALIGN(vring_size(rvring->len, rvring->align)); 343
344 /* make sure reserved bytes are zeroes */
345 if (vring->reserved) {
346 dev_err(dev, "vring rsc has non zero reserved bytes\n");
347 return -EINVAL;
348 }
360 349
361 dma_free_coherent(rproc->dev, size, rvring->va, rvring->dma); 350 /* verify queue size and vring alignment are sane */
362 idr_remove(&rproc->notifyids, rvring->notifyid); 351 if (!vring->num || !vring->align) {
352 dev_err(dev, "invalid qsz (%d) or alignment (%d)\n",
353 vring->num, vring->align);
354 return -EINVAL;
363 } 355 }
356
357 rvring->len = vring->num;
358 rvring->align = vring->align;
359 rvring->rvdev = rvdev;
360
361 return 0;
362}
363
364void rproc_free_vring(struct rproc_vring *rvring)
365{
366 int size = PAGE_ALIGN(vring_size(rvring->len, rvring->align));
367 struct rproc *rproc = rvring->rvdev->rproc;
368
369 dma_free_coherent(rproc->dev, size, rvring->va, rvring->dma);
370 idr_remove(&rproc->notifyids, rvring->notifyid);
364} 371}
365 372
366/** 373/**
@@ -425,11 +432,11 @@ static int rproc_handle_vdev(struct rproc *rproc, struct fw_rsc_vdev *rsc,
425 432
426 rvdev->rproc = rproc; 433 rvdev->rproc = rproc;
427 434
428 /* allocate the vrings */ 435 /* parse the vrings */
429 for (i = 0; i < rsc->num_of_vrings; i++) { 436 for (i = 0; i < rsc->num_of_vrings; i++) {
430 ret = __rproc_handle_vring(rvdev, rsc, i); 437 ret = rproc_parse_vring(rvdev, rsc, i);
431 if (ret) 438 if (ret)
432 goto free_vrings; 439 goto free_rvdev;
433 } 440 }
434 441
435 /* remember the device features */ 442 /* remember the device features */
@@ -440,12 +447,11 @@ static int rproc_handle_vdev(struct rproc *rproc, struct fw_rsc_vdev *rsc,
440 /* it is now safe to add the virtio device */ 447 /* it is now safe to add the virtio device */
441 ret = rproc_add_virtio_dev(rvdev, rsc->id); 448 ret = rproc_add_virtio_dev(rvdev, rsc->id);
442 if (ret) 449 if (ret)
443 goto free_vrings; 450 goto free_rvdev;
444 451
445 return 0; 452 return 0;
446 453
447free_vrings: 454free_rvdev:
448 __rproc_free_vrings(rvdev, i);
449 kfree(rvdev); 455 kfree(rvdev);
450 return ret; 456 return ret;
451} 457}
@@ -1264,18 +1270,11 @@ EXPORT_SYMBOL(rproc_shutdown);
1264void rproc_release(struct kref *kref) 1270void rproc_release(struct kref *kref)
1265{ 1271{
1266 struct rproc *rproc = container_of(kref, struct rproc, refcount); 1272 struct rproc *rproc = container_of(kref, struct rproc, refcount);
1267 struct rproc_vdev *rvdev, *rvtmp;
1268 1273
1269 dev_info(rproc->dev, "removing %s\n", rproc->name); 1274 dev_info(rproc->dev, "removing %s\n", rproc->name);
1270 1275
1271 rproc_delete_debug_dir(rproc); 1276 rproc_delete_debug_dir(rproc);
1272 1277
1273 /* clean up remote vdev entries */
1274 list_for_each_entry_safe(rvdev, rvtmp, &rproc->rvdevs, node) {
1275 __rproc_free_vrings(rvdev, RVDEV_NUM_VRINGS);
1276 list_del(&rvdev->node);
1277 }
1278
1279 /* 1278 /*
1280 * At this point no one holds a reference to rproc anymore, 1279 * At this point no one holds a reference to rproc anymore,
1281 * so we can directly unroll rproc_alloc() 1280 * so we can directly unroll rproc_alloc()
@@ -1546,7 +1545,7 @@ EXPORT_SYMBOL(rproc_free);
1546 */ 1545 */
1547int rproc_unregister(struct rproc *rproc) 1546int rproc_unregister(struct rproc *rproc)
1548{ 1547{
1549 struct rproc_vdev *rvdev; 1548 struct rproc_vdev *rvdev, *tmp;
1550 1549
1551 if (!rproc) 1550 if (!rproc)
1552 return -EINVAL; 1551 return -EINVAL;
@@ -1555,7 +1554,7 @@ int rproc_unregister(struct rproc *rproc)
1555 wait_for_completion(&rproc->firmware_loading_complete); 1554 wait_for_completion(&rproc->firmware_loading_complete);
1556 1555
1557 /* clean up remote vdev entries */ 1556 /* clean up remote vdev entries */
1558 list_for_each_entry(rvdev, &rproc->rvdevs, node) 1557 list_for_each_entry_safe(rvdev, tmp, &rproc->rvdevs, node)
1559 rproc_remove_virtio_dev(rvdev); 1558 rproc_remove_virtio_dev(rvdev);
1560 1559
1561 /* the rproc is downref'ed as soon as it's removed from the klist */ 1560 /* the rproc is downref'ed as soon as it's removed from the klist */
diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
index 9f336d6bdef3..f4957cfa0883 100644
--- a/drivers/remoteproc/remoteproc_internal.h
+++ b/drivers/remoteproc/remoteproc_internal.h
@@ -41,4 +41,6 @@ void rproc_create_debug_dir(struct rproc *rproc);
41void rproc_init_debugfs(void); 41void rproc_init_debugfs(void);
42void rproc_exit_debugfs(void); 42void rproc_exit_debugfs(void);
43 43
44void rproc_free_vring(struct rproc_vring *rvring);
45int rproc_alloc_vring(struct rproc_vdev *rvdev, int i);
44#endif /* REMOTEPROC_INTERNAL_H */ 46#endif /* REMOTEPROC_INTERNAL_H */
diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
index ecf612130750..26a7144e7f3b 100644
--- a/drivers/remoteproc/remoteproc_virtio.c
+++ b/drivers/remoteproc/remoteproc_virtio.c
@@ -77,14 +77,17 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev,
77 struct rproc_vring *rvring; 77 struct rproc_vring *rvring;
78 struct virtqueue *vq; 78 struct virtqueue *vq;
79 void *addr; 79 void *addr;
80 int len, size; 80 int len, size, ret;
81 81
82 /* we're temporarily limited to two virtqueues per rvdev */ 82 /* we're temporarily limited to two virtqueues per rvdev */
83 if (id >= ARRAY_SIZE(rvdev->vring)) 83 if (id >= ARRAY_SIZE(rvdev->vring))
84 return ERR_PTR(-EINVAL); 84 return ERR_PTR(-EINVAL);
85 85
86 rvring = &rvdev->vring[id]; 86 ret = rproc_alloc_vring(rvdev, id);
87 if (ret)
88 return ERR_PTR(ret);
87 89
90 rvring = &rvdev->vring[id];
88 addr = rvring->va; 91 addr = rvring->va;
89 len = rvring->len; 92 len = rvring->len;
90 93
@@ -103,6 +106,7 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev,
103 rproc_virtio_notify, callback, name); 106 rproc_virtio_notify, callback, name);
104 if (!vq) { 107 if (!vq) {
105 dev_err(rproc->dev, "vring_new_virtqueue %s failed\n", name); 108 dev_err(rproc->dev, "vring_new_virtqueue %s failed\n", name);
109 rproc_free_vring(rvring);
106 return ERR_PTR(-ENOMEM); 110 return ERR_PTR(-ENOMEM);
107 } 111 }
108 112
@@ -125,6 +129,7 @@ static void rproc_virtio_del_vqs(struct virtio_device *vdev)
125 rvring = vq->priv; 129 rvring = vq->priv;
126 rvring->vq = NULL; 130 rvring->vq = NULL;
127 vring_del_virtqueue(vq); 131 vring_del_virtqueue(vq);
132 rproc_free_vring(rvring);
128 } 133 }
129} 134}
130 135
@@ -228,8 +233,12 @@ static struct virtio_config_ops rproc_virtio_config_ops = {
228static void rproc_vdev_release(struct device *dev) 233static void rproc_vdev_release(struct device *dev)
229{ 234{
230 struct virtio_device *vdev = dev_to_virtio(dev); 235 struct virtio_device *vdev = dev_to_virtio(dev);
236 struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
231 struct rproc *rproc = vdev_to_rproc(vdev); 237 struct rproc *rproc = vdev_to_rproc(vdev);
232 238
239 list_del(&rvdev->node);
240 kfree(rvdev);
241
233 kref_put(&rproc->refcount, rproc_release); 242 kref_put(&rproc->refcount, rproc_release);
234} 243}
235 244