diff options
author | Michael S. Tsirkin <mst@redhat.com> | 2020-07-27 10:51:55 -0400 |
---|---|---|
committer | Michael S. Tsirkin <mst@redhat.com> | 2020-08-05 11:08:40 -0400 |
commit | 452639a64ad880792652b6d20cc5c8dd4ecf27d9 (patch) | |
tree | 0823155f820d8a15fcafc98864df67e695bcc437 /include/linux/vdpa.h | |
parent | 03bea764bf61c9f9918324bda7362616024386e8 (diff) | |
download | lwn-452639a64ad880792652b6d20cc5c8dd4ecf27d9.tar.gz lwn-452639a64ad880792652b6d20cc5c8dd4ecf27d9.zip |
vdpa: make sure set_features is invoked for legacy
Some legacy guests just assume features are 0 after reset.
We detect that config space is accessed before features are
set and set features to 0 automatically.
Note: some legacy guests might not even access config space, if this is
reported in the field we might need to catch a kick to handle these.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'include/linux/vdpa.h')
-rw-r--r-- | include/linux/vdpa.h | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/include/linux/vdpa.h b/include/linux/vdpa.h index 239db794357c..29b8296f1414 100644 --- a/include/linux/vdpa.h +++ b/include/linux/vdpa.h @@ -33,12 +33,14 @@ struct vdpa_notification_area { * @dma_dev: the actual device that is performing DMA * @config: the configuration ops for this device. * @index: device index + * @features_valid: were features initialized? for legacy guests */ struct vdpa_device { struct device dev; struct device *dma_dev; const struct vdpa_config_ops *config; unsigned int index; + bool features_valid; }; /** @@ -266,4 +268,36 @@ static inline struct device *vdpa_get_dma_dev(struct vdpa_device *vdev) { return vdev->dma_dev; } + +static inline void vdpa_reset(struct vdpa_device *vdev) +{ + const struct vdpa_config_ops *ops = vdev->config; + + vdev->features_valid = false; + ops->set_status(vdev, 0); +} + +static inline int vdpa_set_features(struct vdpa_device *vdev, u64 features) +{ + const struct vdpa_config_ops *ops = vdev->config; + + vdev->features_valid = true; + return ops->set_features(vdev, features); +} + + +static inline void vdpa_get_config(struct vdpa_device *vdev, unsigned offset, + void *buf, unsigned int len) +{ + const struct vdpa_config_ops *ops = vdev->config; + + /* + * Config accesses aren't supposed to trigger before features are set. + * If it does happen we assume a legacy guest. + */ + if (!vdev->features_valid) + vdpa_set_features(vdev, 0); + ops->get_config(vdev, offset, buf, len); +} + #endif /* _LINUX_VDPA_H */ |