diff options
Diffstat (limited to 'drivers/remoteproc/remoteproc_virtio.c')
| -rw-r--r-- | drivers/remoteproc/remoteproc_virtio.c | 84 |
1 files changed, 67 insertions, 17 deletions
diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c index 9e198e59067..a34b50690b4 100644 --- a/drivers/remoteproc/remoteproc_virtio.c +++ b/drivers/remoteproc/remoteproc_virtio.c @@ -30,7 +30,7 @@ #include "remoteproc_internal.h" /* kick the remote processor, and let it know which virtqueue to poke at */ -static void rproc_virtio_notify(struct virtqueue *vq) +static bool rproc_virtio_notify(struct virtqueue *vq) { struct rproc_vring *rvring = vq->priv; struct rproc *rproc = rvring->rvdev->rproc; @@ -39,6 +39,7 @@ static void rproc_virtio_notify(struct virtqueue *vq) dev_dbg(&rproc->dev, "kicking vq index: %d\n", notifyid); rproc->ops->kick(rproc, notifyid); + return true; } /** @@ -173,25 +174,35 @@ error: return ret; } -/* - * We don't support yet real virtio status semantics. - * - * The plan is to provide this via the VDEV resource entry - * which is part of the firmware: this way the remote processor - * will be able to access the status values as set by us. - */ static u8 rproc_virtio_get_status(struct virtio_device *vdev) { - return 0; + struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); + struct fw_rsc_vdev *rsc; + + rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset; + + return rsc->status; } static void rproc_virtio_set_status(struct virtio_device *vdev, u8 status) { + struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); + struct fw_rsc_vdev *rsc; + + rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset; + + rsc->status = status; dev_dbg(&vdev->dev, "status: %d\n", status); } static void rproc_virtio_reset(struct virtio_device *vdev) { + struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); + struct fw_rsc_vdev *rsc; + + rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset; + + rsc->status = 0; dev_dbg(&vdev->dev, "reset !\n"); } @@ -199,13 +210,19 @@ static void rproc_virtio_reset(struct virtio_device *vdev) static u32 rproc_virtio_get_features(struct virtio_device *vdev) { struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); + struct fw_rsc_vdev *rsc; + + rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset; - return rvdev->dfeatures; + return rsc->dfeatures; } static void rproc_virtio_finalize_features(struct virtio_device *vdev) { struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); + struct fw_rsc_vdev *rsc; + + rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset; /* Give virtio_ring a chance to accept features */ vring_transport_features(vdev); @@ -213,16 +230,47 @@ static void rproc_virtio_finalize_features(struct virtio_device *vdev) /* * Remember the finalized features of our vdev, and provide it * to the remote processor once it is powered on. - * - * Similarly to the status field, we don't expose yet the negotiated - * features to the remote processors at this point. This will be - * fixed as part of a small resource table overhaul and then an - * extension of the virtio resource entries. */ - rvdev->gfeatures = vdev->features[0]; + rsc->gfeatures = vdev->features[0]; +} + +static void rproc_virtio_get(struct virtio_device *vdev, unsigned offset, + void *buf, unsigned len) +{ + struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); + struct fw_rsc_vdev *rsc; + void *cfg; + + rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset; + cfg = &rsc->vring[rsc->num_of_vrings]; + + if (offset + len > rsc->config_len || offset + len < len) { + dev_err(&vdev->dev, "rproc_virtio_get: access out of bounds\n"); + return; + } + + memcpy(buf, cfg + offset, len); +} + +static void rproc_virtio_set(struct virtio_device *vdev, unsigned offset, + const void *buf, unsigned len) +{ + struct rproc_vdev *rvdev = vdev_to_rvdev(vdev); + struct fw_rsc_vdev *rsc; + void *cfg; + + rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset; + cfg = &rsc->vring[rsc->num_of_vrings]; + + if (offset + len > rsc->config_len || offset + len < len) { + dev_err(&vdev->dev, "rproc_virtio_set: access out of bounds\n"); + return; + } + + 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, @@ -230,6 +278,8 @@ static struct virtio_config_ops rproc_virtio_config_ops = { .reset = rproc_virtio_reset, .set_status = rproc_virtio_set_status, .get_status = rproc_virtio_get_status, + .get = rproc_virtio_get, + .set = rproc_virtio_set, }; /* |
