diff options
Diffstat (limited to 'drivers/remoteproc/remoteproc_virtio.c')
| -rw-r--r-- | drivers/remoteproc/remoteproc_virtio.c | 79 | 
1 files changed, 64 insertions, 15 deletions
diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c index afed9b7731c..b09c75c21b6 100644 --- a/drivers/remoteproc/remoteproc_virtio.c +++ b/drivers/remoteproc/remoteproc_virtio.c @@ -173,25 +173,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 +209,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,13 +229,44 @@ 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 const struct virtio_config_ops rproc_virtio_config_ops = { @@ -230,6 +277,8 @@ static const 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,  };  /*  |