@@ -98,8 +98,10 @@ static void vfio_ccw_sch_io_todo(struct work_struct *work)
memcpy(private->io_region->irb_area, irb, sizeof(*irb));
mutex_unlock(&private->io_mutex);
- if (private->mdev && scsw_is_solicited(&irb->scsw) && is_final)
+ if (private->mdev && scsw_is_solicited(&irb->scsw) && is_final) {
private->state = VFIO_CCW_STATE_IDLE;
+ private->scsw.cmd.actl &= ~SCSW_ACTL_START_PEND;
+ }
if (private->io_trigger)
eventfd_signal(private->io_trigger, 1);
@@ -246,8 +246,20 @@ static void fsm_io_request(struct vfio_ccw_private *private,
char *errstr = "request";
struct subchannel_id schid = get_schid(private);
+ if (scsw_actl(scsw) & SCSW_ACTL_START_PEND) {
+ io_region->ret_code = -EBUSY;
+ VFIO_CCW_MSG_EVENT(2,
+ "%pUl (%x.%x.%04x): actl %x pending\n",
+ mdev_uuid(mdev), schid.cssid,
+ schid.ssid, schid.sch_no,
+ scsw_actl(scsw));
+ errstr = "pending";
+ goto err_out;
+ }
+
private->state = VFIO_CCW_STATE_CP_PROCESSING;
memcpy(scsw, io_region->scsw_area, sizeof(*scsw));
+ scsw->cmd.actl |= SCSW_ACTL_START_PEND;
if (scsw->cmd.fctl & SCSW_FCTL_START_FUNC) {
orb = (union orb *)io_region->orb_area;
@@ -269,8 +269,10 @@ static ssize_t vfio_ccw_mdev_write_io_region(struct vfio_ccw_private *private,
}
vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_IO_REQ);
- if (region->ret_code != 0)
+ if (region->ret_code != 0) {
private->state = VFIO_CCW_STATE_IDLE;
+ private->scsw.cmd.actl &= ~SCSW_ACTL_START_PEND;
+ }
ret = (region->ret_code != 0) ? region->ret_code : count;
out_unlock: