diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/s390/kvm/virtio_ccw.c | 11 |
1 files changed, 9 insertions, 2 deletions
diff --git a/drivers/s390/kvm/virtio_ccw.c b/drivers/s390/kvm/virtio_ccw.c index 6f1fa1773e76..f8d8fdb26b72 100644 --- a/drivers/s390/kvm/virtio_ccw.c +++ b/drivers/s390/kvm/virtio_ccw.c | |||
| @@ -65,6 +65,7 @@ struct virtio_ccw_device { | |||
| 65 | bool is_thinint; | 65 | bool is_thinint; |
| 66 | bool going_away; | 66 | bool going_away; |
| 67 | bool device_lost; | 67 | bool device_lost; |
| 68 | unsigned int config_ready; | ||
| 68 | void *airq_info; | 69 | void *airq_info; |
| 69 | }; | 70 | }; |
| 70 | 71 | ||
| @@ -833,8 +834,11 @@ static void virtio_ccw_get_config(struct virtio_device *vdev, | |||
| 833 | if (ret) | 834 | if (ret) |
| 834 | goto out_free; | 835 | goto out_free; |
| 835 | 836 | ||
| 836 | memcpy(vcdev->config, config_area, sizeof(vcdev->config)); | 837 | memcpy(vcdev->config, config_area, offset + len); |
| 837 | memcpy(buf, &vcdev->config[offset], len); | 838 | if (buf) |
| 839 | memcpy(buf, &vcdev->config[offset], len); | ||
| 840 | if (vcdev->config_ready < offset + len) | ||
| 841 | vcdev->config_ready = offset + len; | ||
| 838 | 842 | ||
| 839 | out_free: | 843 | out_free: |
| 840 | kfree(config_area); | 844 | kfree(config_area); |
| @@ -857,6 +861,9 @@ static void virtio_ccw_set_config(struct virtio_device *vdev, | |||
| 857 | if (!config_area) | 861 | if (!config_area) |
| 858 | goto out_free; | 862 | goto out_free; |
| 859 | 863 | ||
| 864 | /* Make sure we don't overwrite fields. */ | ||
| 865 | if (vcdev->config_ready < offset) | ||
| 866 | virtio_ccw_get_config(vdev, 0, NULL, offset); | ||
| 860 | memcpy(&vcdev->config[offset], buf, len); | 867 | memcpy(&vcdev->config[offset], buf, len); |
| 861 | /* Write the config area to the host. */ | 868 | /* Write the config area to the host. */ |
| 862 | memcpy(config_area, vcdev->config, sizeof(vcdev->config)); | 869 | memcpy(config_area, vcdev->config, sizeof(vcdev->config)); |
