hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/drivers/remoteproc/remoteproc_virtio.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Remote processor messaging transport (OMAP platform-specific bits)
34 *
....@@ -6,18 +7,11 @@
67 *
78 * Ohad Ben-Cohen <ohad@wizery.com>
89 * Brian Swetland <swetland@google.com>
9
- *
10
- * This software is licensed under the terms of the GNU General Public
11
- * License version 2, as published by the Free Software Foundation, and
12
- * may be copied, distributed, and modified under those terms.
13
- *
14
- * This program is distributed in the hope that it will be useful,
15
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
- * GNU General Public License for more details.
1810 */
1911
12
+#include <linux/dma-map-ops.h>
2013 #include <linux/export.h>
14
+#include <linux/of_reserved_mem.h>
2115 #include <linux/remoteproc.h>
2216 #include <linux/virtio.h>
2317 #include <linux/virtio_config.h>
....@@ -76,7 +70,9 @@
7670 struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
7771 struct rproc *rproc = vdev_to_rproc(vdev);
7872 struct device *dev = &rproc->dev;
73
+ struct rproc_mem_entry *mem;
7974 struct rproc_vring *rvring;
75
+ struct fw_rsc_vdev *rsc;
8076 struct virtqueue *vq;
8177 void *addr;
8278 int len, size;
....@@ -88,8 +84,14 @@
8884 if (!name)
8985 return NULL;
9086
87
+ /* Search allocated memory region by name */
88
+ mem = rproc_find_carveout_by_name(rproc, "vdev%dvring%d", rvdev->index,
89
+ id);
90
+ if (!mem || !mem->va)
91
+ return ERR_PTR(-ENOMEM);
92
+
9193 rvring = &rvdev->vring[id];
92
- addr = rvring->va;
94
+ addr = mem->va;
9395 len = rvring->len;
9496
9597 /* zero vring */
....@@ -113,6 +115,10 @@
113115
114116 rvring->vq = vq;
115117 vq->priv = rvring;
118
+
119
+ /* Update vring in resource table */
120
+ rsc = (void *)rproc->table_ptr + rvdev->rsc_offset;
121
+ rsc->vring[id].da = mem->da;
116122
117123 return vq;
118124 }
....@@ -141,10 +147,15 @@
141147 const bool * ctx,
142148 struct irq_affinity *desc)
143149 {
144
- int i, ret;
150
+ int i, ret, queue_idx = 0;
145151
146152 for (i = 0; i < nvqs; ++i) {
147
- vqs[i] = rp_find_vq(vdev, i, callbacks[i], names[i],
153
+ if (!names[i]) {
154
+ vqs[i] = NULL;
155
+ continue;
156
+ }
157
+
158
+ vqs[i] = rp_find_vq(vdev, queue_idx++, callbacks[i], names[i],
148159 ctx ? ctx[i] : false);
149160 if (IS_ERR(vqs[i])) {
150161 ret = PTR_ERR(vqs[i]);
....@@ -202,6 +213,16 @@
202213 return rsc->dfeatures;
203214 }
204215
216
+static void rproc_transport_features(struct virtio_device *vdev)
217
+{
218
+ /*
219
+ * Packed ring isn't enabled on remoteproc for now,
220
+ * because remoteproc uses vring_new_virtqueue() which
221
+ * creates virtio rings on preallocated memory.
222
+ */
223
+ __virtio_clear_bit(vdev, VIRTIO_F_RING_PACKED);
224
+}
225
+
205226 static int rproc_virtio_finalize_features(struct virtio_device *vdev)
206227 {
207228 struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
....@@ -211,6 +232,9 @@
211232
212233 /* Give virtio_ring a chance to accept features */
213234 vring_transport_features(vdev);
235
+
236
+ /* Give virtio_rproc a chance to accept features. */
237
+ rproc_transport_features(vdev);
214238
215239 /* Make sure we don't have any features > 32 bits! */
216240 BUG_ON((u32)vdev->features != vdev->features);
....@@ -286,6 +310,8 @@
286310 struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
287311 struct rproc *rproc = vdev_to_rproc(vdev);
288312
313
+ kfree(vdev);
314
+
289315 kref_put(&rvdev->refcount, rproc_vdev_release);
290316
291317 put_device(&rproc->dev);
....@@ -294,6 +320,7 @@
294320 /**
295321 * rproc_add_virtio_dev() - register an rproc-induced virtio device
296322 * @rvdev: the remote vdev
323
+ * @id: the device type identification (used to match it with a driver).
297324 *
298325 * This function registers a virtio device. This vdev's partent is
299326 * the rproc device.
....@@ -303,10 +330,71 @@
303330 int rproc_add_virtio_dev(struct rproc_vdev *rvdev, int id)
304331 {
305332 struct rproc *rproc = rvdev->rproc;
306
- struct device *dev = &rproc->dev;
307
- struct virtio_device *vdev = &rvdev->vdev;
333
+ struct device *dev = &rvdev->dev;
334
+ struct virtio_device *vdev;
335
+ struct rproc_mem_entry *mem;
308336 int ret;
309337
338
+ if (rproc->ops->kick == NULL) {
339
+ ret = -EINVAL;
340
+ dev_err(dev, ".kick method not defined for %s\n", rproc->name);
341
+ goto out;
342
+ }
343
+
344
+ /* Try to find dedicated vdev buffer carveout */
345
+ mem = rproc_find_carveout_by_name(rproc, "vdev%dbuffer", rvdev->index);
346
+ if (mem) {
347
+ phys_addr_t pa;
348
+
349
+ if (mem->of_resm_idx != -1) {
350
+ struct device_node *np = rproc->dev.parent->of_node;
351
+
352
+ /* Associate reserved memory to vdev device */
353
+ ret = of_reserved_mem_device_init_by_idx(dev, np,
354
+ mem->of_resm_idx);
355
+ if (ret) {
356
+ dev_err(dev, "Can't associate reserved memory\n");
357
+ goto out;
358
+ }
359
+ } else {
360
+ if (mem->va) {
361
+ dev_warn(dev, "vdev %d buffer already mapped\n",
362
+ rvdev->index);
363
+ pa = rproc_va_to_pa(mem->va);
364
+ } else {
365
+ /* Use dma address as carveout no memmapped yet */
366
+ pa = (phys_addr_t)mem->dma;
367
+ }
368
+
369
+ /* Associate vdev buffer memory pool to vdev subdev */
370
+ ret = dma_declare_coherent_memory(dev, pa,
371
+ mem->da,
372
+ mem->len);
373
+ if (ret < 0) {
374
+ dev_err(dev, "Failed to associate buffer\n");
375
+ goto out;
376
+ }
377
+ }
378
+ } else {
379
+ struct device_node *np = rproc->dev.parent->of_node;
380
+
381
+ /*
382
+ * If we don't have dedicated buffer, just attempt to re-assign
383
+ * the reserved memory from our parent. A default memory-region
384
+ * at index 0 from the parent's memory-regions is assigned for
385
+ * the rvdev dev to allocate from. Failure is non-critical and
386
+ * the allocations will fall back to global pools, so don't
387
+ * check return value either.
388
+ */
389
+ of_reserved_mem_device_init_by_idx(dev, np, 0);
390
+ }
391
+
392
+ /* Allocate virtio device */
393
+ vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
394
+ if (!vdev) {
395
+ ret = -ENOMEM;
396
+ goto out;
397
+ }
310398 vdev->id.device = id,
311399 vdev->config = &rproc_virtio_config_ops,
312400 vdev->dev.parent = dev;
....@@ -340,11 +428,15 @@
340428
341429 /**
342430 * rproc_remove_virtio_dev() - remove an rproc-induced virtio device
343
- * @rvdev: the remote vdev
431
+ * @dev: the virtio device
432
+ * @data: must be null
344433 *
345434 * This function unregisters an existing virtio device.
346435 */
347
-void rproc_remove_virtio_dev(struct rproc_vdev *rvdev)
436
+int rproc_remove_virtio_dev(struct device *dev, void *data)
348437 {
349
- unregister_virtio_device(&rvdev->vdev);
438
+ struct virtio_device *vdev = dev_to_virtio(dev);
439
+
440
+ unregister_virtio_device(vdev);
441
+ return 0;
350442 }