|
@@ -984,6 +984,36 @@ static struct virtqueue *virtio_ccw_vq_by_ind(struct virtio_ccw_device *vcdev,
|
|
return vq;
|
|
return vq;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void virtio_ccw_check_activity(struct virtio_ccw_device *vcdev,
|
|
|
|
+ __u32 activity)
|
|
|
|
+{
|
|
|
|
+ if (vcdev->curr_io & activity) {
|
|
|
|
+ switch (activity) {
|
|
|
|
+ case VIRTIO_CCW_DOING_READ_FEAT:
|
|
|
|
+ case VIRTIO_CCW_DOING_WRITE_FEAT:
|
|
|
|
+ case VIRTIO_CCW_DOING_READ_CONFIG:
|
|
|
|
+ case VIRTIO_CCW_DOING_WRITE_CONFIG:
|
|
|
|
+ case VIRTIO_CCW_DOING_WRITE_STATUS:
|
|
|
|
+ case VIRTIO_CCW_DOING_SET_VQ:
|
|
|
|
+ case VIRTIO_CCW_DOING_SET_IND:
|
|
|
|
+ case VIRTIO_CCW_DOING_SET_CONF_IND:
|
|
|
|
+ case VIRTIO_CCW_DOING_RESET:
|
|
|
|
+ case VIRTIO_CCW_DOING_READ_VQ_CONF:
|
|
|
|
+ case VIRTIO_CCW_DOING_SET_IND_ADAPTER:
|
|
|
|
+ case VIRTIO_CCW_DOING_SET_VIRTIO_REV:
|
|
|
|
+ vcdev->curr_io &= ~activity;
|
|
|
|
+ wake_up(&vcdev->wait_q);
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ /* don't know what to do... */
|
|
|
|
+ dev_warn(&vcdev->cdev->dev,
|
|
|
|
+ "Suspicious activity '%08x'\n", activity);
|
|
|
|
+ WARN_ON(1);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
static void virtio_ccw_int_handler(struct ccw_device *cdev,
|
|
static void virtio_ccw_int_handler(struct ccw_device *cdev,
|
|
unsigned long intparm,
|
|
unsigned long intparm,
|
|
struct irb *irb)
|
|
struct irb *irb)
|
|
@@ -995,6 +1025,12 @@ static void virtio_ccw_int_handler(struct ccw_device *cdev,
|
|
|
|
|
|
if (!vcdev)
|
|
if (!vcdev)
|
|
return;
|
|
return;
|
|
|
|
+ if (IS_ERR(irb)) {
|
|
|
|
+ vcdev->err = PTR_ERR(irb);
|
|
|
|
+ virtio_ccw_check_activity(vcdev, activity);
|
|
|
|
+ /* Don't poke around indicators, something's wrong. */
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
/* Check if it's a notification from the host. */
|
|
/* Check if it's a notification from the host. */
|
|
if ((intparm == 0) &&
|
|
if ((intparm == 0) &&
|
|
(scsw_stctl(&irb->scsw) ==
|
|
(scsw_stctl(&irb->scsw) ==
|
|
@@ -1010,31 +1046,7 @@ static void virtio_ccw_int_handler(struct ccw_device *cdev,
|
|
/* Map everything else to -EIO. */
|
|
/* Map everything else to -EIO. */
|
|
vcdev->err = -EIO;
|
|
vcdev->err = -EIO;
|
|
}
|
|
}
|
|
- if (vcdev->curr_io & activity) {
|
|
|
|
- switch (activity) {
|
|
|
|
- case VIRTIO_CCW_DOING_READ_FEAT:
|
|
|
|
- case VIRTIO_CCW_DOING_WRITE_FEAT:
|
|
|
|
- case VIRTIO_CCW_DOING_READ_CONFIG:
|
|
|
|
- case VIRTIO_CCW_DOING_WRITE_CONFIG:
|
|
|
|
- case VIRTIO_CCW_DOING_WRITE_STATUS:
|
|
|
|
- case VIRTIO_CCW_DOING_SET_VQ:
|
|
|
|
- case VIRTIO_CCW_DOING_SET_IND:
|
|
|
|
- case VIRTIO_CCW_DOING_SET_CONF_IND:
|
|
|
|
- case VIRTIO_CCW_DOING_RESET:
|
|
|
|
- case VIRTIO_CCW_DOING_READ_VQ_CONF:
|
|
|
|
- case VIRTIO_CCW_DOING_SET_IND_ADAPTER:
|
|
|
|
- case VIRTIO_CCW_DOING_SET_VIRTIO_REV:
|
|
|
|
- vcdev->curr_io &= ~activity;
|
|
|
|
- wake_up(&vcdev->wait_q);
|
|
|
|
- break;
|
|
|
|
- default:
|
|
|
|
- /* don't know what to do... */
|
|
|
|
- dev_warn(&cdev->dev, "Suspicious activity '%08x'\n",
|
|
|
|
- activity);
|
|
|
|
- WARN_ON(1);
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ virtio_ccw_check_activity(vcdev, activity);
|
|
for_each_set_bit(i, &vcdev->indicators,
|
|
for_each_set_bit(i, &vcdev->indicators,
|
|
sizeof(vcdev->indicators) * BITS_PER_BYTE) {
|
|
sizeof(vcdev->indicators) * BITS_PER_BYTE) {
|
|
/* The bit clear must happen before the vring kick. */
|
|
/* The bit clear must happen before the vring kick. */
|