Pull virtio fix from Michael Tsirkin: "This includes a single fix for virtio ccw error handling" * tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost: virtio/s390: handle error values in irb
Unified · Split
| @@ -984,6 +984,36 @@ static struct virtqueue *virtio_ccw_vq_by_ind(struct virtio_ccw_device *vcdev, · 983 unmodified lines | ||
| 984 | 984 | return vq; |
| 985 | 985 | } |
| 986 | 986 | |
| 987 | +static void virtio_ccw_check_activity(struct virtio_ccw_device *vcdev, | |
| 988 | + __u32 activity) | |
| 989 | +{ | |
| 990 | + if (vcdev->curr_io & activity) { | |
| 991 | + switch (activity) { | |
| 992 | + case VIRTIO_CCW_DOING_READ_FEAT: | |
| 993 | + case VIRTIO_CCW_DOING_WRITE_FEAT: | |
| 994 | + case VIRTIO_CCW_DOING_READ_CONFIG: | |
| 995 | + case VIRTIO_CCW_DOING_WRITE_CONFIG: | |
| 996 | + case VIRTIO_CCW_DOING_WRITE_STATUS: | |
| 997 | + case VIRTIO_CCW_DOING_SET_VQ: | |
| 998 | + case VIRTIO_CCW_DOING_SET_IND: | |
| 999 | + case VIRTIO_CCW_DOING_SET_CONF_IND: | |
| 1000 | + case VIRTIO_CCW_DOING_RESET: | |
| 1001 | + case VIRTIO_CCW_DOING_READ_VQ_CONF: | |
| 1002 | + case VIRTIO_CCW_DOING_SET_IND_ADAPTER: | |
| 1003 | + case VIRTIO_CCW_DOING_SET_VIRTIO_REV: | |
| 1004 | + vcdev->curr_io &= ~activity; | |
| 1005 | + wake_up(&vcdev->wait_q); | |
| 1006 | + break; | |
| 1007 | + default: | |
| 1008 | + /* don't know what to do... */ | |
| 1009 | + dev_warn(&vcdev->cdev->dev, | |
| 1010 | + "Suspicious activity '%08x'\n", activity); | |
| 1011 | + WARN_ON(1); | |
| 1012 | + break; | |
| 1013 | + } | |
| 1014 | + } | |
| 1015 | +} | |
| 1016 | + | |
| 987 | 1017 | static void virtio_ccw_int_handler(struct ccw_device *cdev, |
| 988 | 1018 | unsigned long intparm, |
| 989 | 1019 | struct irb *irb) |
| @@ -995,6 +1025,12 @@ static void virtio_ccw_int_handler(struct ccw_device *cdev, · 5 unmodified lines | ||
| 995 | 1025 | |
| 996 | 1026 | if (!vcdev) |
| 997 | 1027 | return; |
| 1028 | + if (IS_ERR(irb)) { | |
| 1029 | + vcdev->err = PTR_ERR(irb); | |
| 1030 | + virtio_ccw_check_activity(vcdev, activity); | |
| 1031 | + /* Don't poke around indicators, something's wrong. */ | |
| 1032 | + return; | |
| 1033 | + } | |
| 998 | 1034 | /* Check if it's a notification from the host. */ |
| 999 | 1035 | if ((intparm == 0) && |
| 1000 | 1036 | (scsw_stctl(&irb->scsw) == |
| @@ -1010,31 +1046,7 @@ static void virtio_ccw_int_handler(struct ccw_device *cdev, · 9 unmodified lines | ||
| 1010 | 1046 | /* Map everything else to -EIO. */ |
| 1011 | 1047 | vcdev->err = -EIO; |
| 1012 | 1048 | } |
| 1013 | − if (vcdev->curr_io & activity) { | |
| 1014 | − switch (activity) { | |
| 1015 | − case VIRTIO_CCW_DOING_READ_FEAT: | |
| 1016 | − case VIRTIO_CCW_DOING_WRITE_FEAT: | |
| 1017 | − case VIRTIO_CCW_DOING_READ_CONFIG: | |
| 1018 | − case VIRTIO_CCW_DOING_WRITE_CONFIG: | |
| 1019 | − case VIRTIO_CCW_DOING_WRITE_STATUS: | |
| 1020 | − case VIRTIO_CCW_DOING_SET_VQ: | |
| 1021 | − case VIRTIO_CCW_DOING_SET_IND: | |
| 1022 | − case VIRTIO_CCW_DOING_SET_CONF_IND: | |
| 1023 | − case VIRTIO_CCW_DOING_RESET: | |
| 1024 | − case VIRTIO_CCW_DOING_READ_VQ_CONF: | |
| 1025 | − case VIRTIO_CCW_DOING_SET_IND_ADAPTER: | |
| 1026 | − case VIRTIO_CCW_DOING_SET_VIRTIO_REV: | |
| 1027 | − vcdev->curr_io &= ~activity; | |
| 1028 | − wake_up(&vcdev->wait_q); | |
| 1029 | − break; | |
| 1030 | − default: | |
| 1031 | − /* don't know what to do... */ | |
| 1032 | − dev_warn(&cdev->dev, "Suspicious activity '%08x'\n", | |
| 1033 | − activity); | |
| 1034 | − WARN_ON(1); | |
| 1035 | − break; | |
| 1036 | − } | |
| 1037 | − } | |
| 1049 | + virtio_ccw_check_activity(vcdev, activity); | |
| 1038 | 1050 | for_each_set_bit(i, &vcdev->indicators, |
| 1039 | 1051 | sizeof(vcdev->indicators) * BITS_PER_BYTE) { |
| 1040 | 1052 | /* The bit clear must happen before the vring kick. */ |