--- zzzz-none-000/linux-4.4.271/drivers/remoteproc/remoteproc_virtio.c 2021-06-03 06:22:09.000000000 +0000 +++ hawkeye-5590-750/linux-4.4.271/drivers/remoteproc/remoteproc_virtio.c 2023-04-19 10:22:29.000000000 +0000 @@ -69,17 +69,19 @@ EXPORT_SYMBOL(rproc_vq_interrupt); static struct virtqueue *rp_find_vq(struct virtio_device *vdev, - unsigned id, + unsigned int id, void (*callback)(struct virtqueue *vq), - const char *name) + const char *name, bool ctx) { struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); struct rproc *rproc = vdev_to_rproc(vdev); struct device *dev = &rproc->dev; + struct rproc_mem_entry *mem; struct rproc_vring *rvring; + struct fw_rsc_vdev *rsc; struct virtqueue *vq; void *addr; - int len, size, ret; + int len, size; /* we're temporarily limited to two virtqueues per rvdev */ if (id >= ARRAY_SIZE(rvdev->vring)) @@ -88,27 +90,29 @@ if (!name) return NULL; - ret = rproc_alloc_vring(rvdev, id); - if (ret) - return ERR_PTR(ret); + /* Search allocated memory region by name */ + mem = rproc_find_carveout_by_name(rproc, "vdev%dvring%d", rvdev->index, + id); + if (!mem || !mem->va) + return ERR_PTR(-ENOMEM); rvring = &rvdev->vring[id]; - addr = rvring->va; + addr = mem->va; len = rvring->len; /* zero vring */ size = vring_size(len, rvring->align); memset(addr, 0, size); - dev_dbg(dev, "vring%d: va %p qsz %d notifyid %d\n", - id, addr, len, rvring->notifyid); + dev_dbg(dev, "vring%d: va %pK qsz %d notifyid %d\n", + id, addr, len, rvring->notifyid); /* * Create the new vq, and tell virtio we're not interested in * the 'weak' smp barriers, since we're talking with a real device. */ - vq = vring_new_virtqueue(id, len, rvring->align, vdev, false, addr, - rproc_virtio_notify, callback, name); + vq = vring_new_virtqueue(id, len, rvring->align, vdev, false, ctx, + addr, rproc_virtio_notify, callback, name); if (!vq) { dev_err(dev, "vring_new_virtqueue %s failed\n", name); rproc_free_vring(rvring); @@ -118,6 +122,10 @@ rvring->vq = vq; vq->priv = rvring; + /* Update vring in resource table */ + rsc = (void *)rproc->table_ptr + rvdev->rsc_offset; + rsc->vring[id].da = mem->da; + return vq; } @@ -130,43 +138,37 @@ rvring = vq->priv; rvring->vq = NULL; vring_del_virtqueue(vq); - rproc_free_vring(rvring); } } static void rproc_virtio_del_vqs(struct virtio_device *vdev) { - struct rproc *rproc = vdev_to_rproc(vdev); - - /* power down the remote processor before deleting vqs */ - rproc_shutdown(rproc); - __rproc_virtio_del_vqs(vdev); } -static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs, - struct virtqueue *vqs[], - vq_callback_t *callbacks[], - const char *names[]) +static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned int nvqs, + struct virtqueue *vqs[], + vq_callback_t *callbacks[], + const char * const names[], + const bool * ctx, + struct irq_affinity *desc) { - struct rproc *rproc = vdev_to_rproc(vdev); - int i, ret; + int i, ret, queue_idx = 0; for (i = 0; i < nvqs; ++i) { - vqs[i] = rp_find_vq(vdev, i, callbacks[i], names[i]); + if (!names[i]) { + vqs[i] = NULL; + continue; + } + + vqs[i] = rp_find_vq(vdev, queue_idx++, callbacks[i], names[i], + ctx ? ctx[i] : false); if (IS_ERR(vqs[i])) { ret = PTR_ERR(vqs[i]); goto error; } } - /* now that the vqs are all set, boot the remote processor */ - ret = rproc_boot(rproc); - if (ret) { - dev_err(&rproc->dev, "rproc_boot() failed %d\n", ret); - goto error; - } - return 0; error: @@ -239,8 +241,8 @@ return 0; } -static void rproc_virtio_get(struct virtio_device *vdev, unsigned offset, - void *buf, unsigned len) +static void rproc_virtio_get(struct virtio_device *vdev, unsigned int offset, + void *buf, unsigned int len) { struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); struct fw_rsc_vdev *rsc; @@ -257,8 +259,8 @@ memcpy(buf, cfg + offset, len); } -static void rproc_virtio_set(struct virtio_device *vdev, unsigned offset, - const void *buf, unsigned len) +static void rproc_virtio_set(struct virtio_device *vdev, unsigned int offset, + const void *buf, unsigned int len) { struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); struct fw_rsc_vdev *rsc; @@ -295,14 +297,13 @@ * Never call this function directly; it will be called by the driver * core when needed. */ -static void rproc_vdev_release(struct device *dev) +static void rproc_virtio_dev_release(struct device *dev) { struct virtio_device *vdev = dev_to_virtio(dev); struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); struct rproc *rproc = vdev_to_rproc(vdev); - list_del(&rvdev->node); - kfree(rvdev); + kref_put(&rvdev->refcount, rproc_vdev_release); put_device(&rproc->dev); } @@ -326,7 +327,7 @@ vdev->id.device = id, vdev->config = &rproc_virtio_config_ops, vdev->dev.parent = dev; - vdev->dev.release = rproc_vdev_release; + vdev->dev.release = rproc_virtio_dev_release; /* * We're indirectly making a non-temporary copy of the rproc pointer @@ -338,9 +339,12 @@ */ get_device(&rproc->dev); + /* Reference the vdev and vring allocations */ + kref_get(&rvdev->refcount); + ret = register_virtio_device(vdev); if (ret) { - put_device(&rproc->dev); + put_device(&vdev->dev); dev_err(dev, "failed to register vdev: %d\n", ret); goto out; }