return ret;
}
- rvdev->dfeatures,
+/**
+ * rproc_virtio_new_vringh() - create a reversed virtio ring.
+ * @vdev: the virtio device
+ * @index: the virtio ring index
+ * @cb: callback for the reversed virtio ring
+ *
+ * This function should be called by the virtio-driver
+ * before calling find_vqs(). It returns a struct vringh for
+ * accessing the virtio ring.
+ *
+ * Return: struct vhost, or NULL upon error.
+ */
+struct vringh *
+rproc_virtio_new_vringh(struct virtio_device *vdev, unsigned index,
+ irqreturn_t (*cb)(struct virtio_device *vdev,
+ struct vringh *vring))
+{
+ struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
+ struct rproc_vring *rvring;
+ struct vringh *vrh;
+ int err;
+
+ if (index > ARRAY_SIZE(rvdev->vring)) {
+ dev_err(&rvdev->vdev.dev, "bad vring index: %d\n", index);
+ return NULL;
+ }
+
+ vrh = kzalloc(sizeof(*vrh), GFP_KERNEL);
+ if (!vrh)
+ return NULL;
+
+ err = rproc_alloc_vring(rvdev, index);
+ if (err)
+ goto free_vring;
+
+
+ rvring = &rvdev->vring[index];
+ /* zero vring */
+ memset(rvring->va, 0, vring_size(rvring->len, rvring->align));
+ vring_init(&vrh->vring, rvring->len, rvring->va, rvring->align);
+
+ rvring->vringh_cb = cb;
+ rvring->vringh = vrh;
+
+ err = vringh_init_kern(vrh,
++ rvdev->rsc->dfeatures,
+ rvring->len,
+ false,
+ vrh->vring.desc,
+ vrh->vring.avail,
+ vrh->vring.used);
+ if (!err)
+ return vrh;
+
+ dev_err(&vdev->dev, "failed to create vhost: %d\n", err);
+ rproc_free_vring(rvring);
+free_vring:
+ kfree(vrh);
+ return NULL;
+}
+EXPORT_SYMBOL(rproc_virtio_new_vringh);
+
+/**
+ * rproc_virtio_del_vringh() - release a reversed virtio ring.
+ * @vdev: the virtio device
+ * @index: the virtio ring index
+ *
+ * This function release the reversed virtio ring.
+ */
+void rproc_virtio_del_vringh(struct virtio_device *vdev, unsigned index)
+{
+ struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
+ struct rproc_vring *rvring = &rvdev->vring[index];
+ kfree(rvring->vringh);
+ rproc_free_vring(rvring);
+ rvring->vringh_cb = NULL;
+ rvring->vringh = NULL;
+}
+EXPORT_SYMBOL(rproc_virtio_del_vringh);
+
+/**
+ * rproc_virtio_kick_vringh() - kick the remote processor.
+ * @vdev: the virtio device
+ * @index: the virtio ring index
+ *
+ * kick the remote processor, and let it know which vring to poke at
+ */
+void rproc_virtio_kick_vringh(struct virtio_device *vdev, unsigned index)
+{
+ struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
+ struct rproc_vring *rvring = &rvdev->vring[index];
+ struct rproc *rproc = rvring->rvdev->rproc;
+ int notifyid = rvring->notifyid;
+
+ dev_dbg(&rproc->dev, "kicking vq index: %d\n", notifyid);
+
+ rproc->ops->kick(rproc, notifyid);
+}
+EXPORT_SYMBOL(rproc_virtio_kick_vringh);
+
/*
* We don't support yet real virtio status semantics.
*
* fixed as part of a small resource table overhaul and then an
* extension of the virtio resource entries.
*/
- rvdev->gfeatures = vdev->features[0];
+ rvdev->rsc->gfeatures = vdev->features[0];
+ }
+
+ void rproc_virtio_get(struct virtio_device *vdev, unsigned offset,
+ void *buf, unsigned len)
+ {
+ struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
+ void *cfg = &rvdev->rsc->vring[rvdev->rsc->num_of_vrings];
+ if (offset + len > rvdev->rsc->config_len)
+ dev_err(&vdev->dev,
+ "rproc_virtio_get: access out of bounds\n");
+ else
+ memcpy(buf, cfg + offset, len);
+ }
+
+ void rproc_virtio_set(struct virtio_device *vdev, unsigned offset,
+ const void *buf, unsigned len)
+ {
+ struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
+ void *cfg = &rvdev->rsc->vring[rvdev->rsc->num_of_vrings];
+ if (offset + len > rvdev->rsc->config_len)
+ dev_err(&vdev->dev,
+ "rproc_virtio_set: access out of bounds\n");
+ else
+ memcpy(cfg + offset, buf, len);
}
-static struct virtio_config_ops rproc_virtio_config_ops = {
+static const struct virtio_config_ops rproc_virtio_config_ops = {
.get_features = rproc_virtio_get_features,
.finalize_features = rproc_virtio_finalize_features,
.find_vqs = rproc_virtio_find_vqs,