diff options
author | Cornelia Huck <cornelia.huck@de.ibm.com> | 2015-12-03 11:24:00 -0500 |
---|---|---|
committer | Michael S. Tsirkin <mst@redhat.com> | 2015-12-17 03:37:33 -0500 |
commit | 74a599f09bec7419b2490039f0fb33bc8581ef7c (patch) | |
tree | 79139da3ddbac8589a09ac124440d2dfeb6f1f31 | |
parent | 9f9499ae8e6415cefc4fe0a96ad0e27864353c89 (diff) |
virtio/s390: handle error values in irb
The common I/O layer may pass an error value as the irb in the device's
interrupt handler (for classic channel I/O). This won't happen in
current virtio-ccw implementations, but it's better to be safe than
sorry.
Let's just return the error conveyed by the irb and clear any possible
pending I/O indications.
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Reviewed-by: Guenther Hutzl <hutzl@linux.vnet.ibm.com>
Reviewed-by: Pierre Morel <pmorel@linux.vnet.ibm.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
-rw-r--r-- | drivers/s390/virtio/virtio_ccw.c | 62 |
1 files changed, 37 insertions, 25 deletions
diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c index b2a1a81e6fc8..1b831598df7c 100644 --- a/drivers/s390/virtio/virtio_ccw.c +++ b/drivers/s390/virtio/virtio_ccw.c | |||
@@ -984,6 +984,36 @@ static struct virtqueue *virtio_ccw_vq_by_ind(struct virtio_ccw_device *vcdev, | |||
984 | return vq; | 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 | static void virtio_ccw_int_handler(struct ccw_device *cdev, | 1017 | static void virtio_ccw_int_handler(struct ccw_device *cdev, |
988 | unsigned long intparm, | 1018 | unsigned long intparm, |
989 | struct irb *irb) | 1019 | struct irb *irb) |
@@ -995,6 +1025,12 @@ static void virtio_ccw_int_handler(struct ccw_device *cdev, | |||
995 | 1025 | ||
996 | if (!vcdev) | 1026 | if (!vcdev) |
997 | return; | 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 | /* Check if it's a notification from the host. */ | 1034 | /* Check if it's a notification from the host. */ |
999 | if ((intparm == 0) && | 1035 | if ((intparm == 0) && |
1000 | (scsw_stctl(&irb->scsw) == | 1036 | (scsw_stctl(&irb->scsw) == |
@@ -1010,31 +1046,7 @@ static void virtio_ccw_int_handler(struct ccw_device *cdev, | |||
1010 | /* Map everything else to -EIO. */ | 1046 | /* Map everything else to -EIO. */ |
1011 | vcdev->err = -EIO; | 1047 | vcdev->err = -EIO; |
1012 | } | 1048 | } |
1013 | if (vcdev->curr_io & activity) { | 1049 | virtio_ccw_check_activity(vcdev, 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 | } | ||
1038 | for_each_set_bit(i, &vcdev->indicators, | 1050 | for_each_set_bit(i, &vcdev->indicators, |
1039 | sizeof(vcdev->indicators) * BITS_PER_BYTE) { | 1051 | sizeof(vcdev->indicators) * BITS_PER_BYTE) { |
1040 | /* The bit clear must happen before the vring kick. */ | 1052 | /* The bit clear must happen before the vring kick. */ |