From nobody Fri Nov 7 23:54:21 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1548854712138801.0628599221874; Wed, 30 Jan 2019 05:25:12 -0800 (PST) Received: from localhost ([127.0.0.1]:38055 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gopra-0002cG-Hc for importer@patchew.org; Wed, 30 Jan 2019 08:25:10 -0500 Received: from eggs.gnu.org ([209.51.188.92]:36430) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1goppL-00017A-Vl for qemu-devel@nongnu.org; Wed, 30 Jan 2019 08:22:55 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1goppJ-00062E-G5 for qemu-devel@nongnu.org; Wed, 30 Jan 2019 08:22:51 -0500 Received: from mx1.redhat.com ([209.132.183.28]:52006) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1goppJ-0005pM-4Q; Wed, 30 Jan 2019 08:22:49 -0500 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 624693DBDB; Wed, 30 Jan 2019 13:22:30 +0000 (UTC) Received: from localhost (dhcp-192-213.str.redhat.com [10.33.192.213]) by smtp.corp.redhat.com (Postfix) with ESMTPS id E58CF5D96F; Wed, 30 Jan 2019 13:22:26 +0000 (UTC) From: Cornelia Huck To: Halil Pasic , Eric Farman , Farhan Ali , Pierre Morel Date: Wed, 30 Jan 2019 14:22:08 +0100 Message-Id: <20190130132212.7376-3-cohuck@redhat.com> In-Reply-To: <20190130132212.7376-1-cohuck@redhat.com> References: <20190130132212.7376-1-cohuck@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Wed, 30 Jan 2019 13:22:30 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v3 2/6] vfio-ccw: rework ssch state handling X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-s390@vger.kernel.org, kvm@vger.kernel.org, Cornelia Huck , Alex Williamson , qemu-devel@nongnu.org, qemu-s390x@nongnu.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The flow for processing ssch requests can be improved by splitting the BUSY state: - CP_PROCESSING: We reject any user space requests while we are in the process of translating a channel program and submitting it to the hardware. Use -EAGAIN to signal user space that it should retry the request. - CP_PENDING: We have successfully submitted a request with ssch and are now expecting an interrupt. As we can't handle more than one channel program being processed, reject any further requests with -EBUSY. A final interrupt will move us out of this state; this also fixes a latent bug where a non-final interrupt might have freed up a channel program that still was in progress. By making this a separate state, we make it possible to issue a halt or a clear while we're still waiting for the final interrupt for the ssch (in a follow-on patch). It also makes a lot of sense not to preemptively filter out writes to the io_region if we're in an incorrect state: the state machine will handle this correctly. Signed-off-by: Cornelia Huck Reviewed-by: Eric Farman --- drivers/s390/cio/vfio_ccw_drv.c | 8 ++++++-- drivers/s390/cio/vfio_ccw_fsm.c | 19 ++++++++++++++----- drivers/s390/cio/vfio_ccw_ops.c | 2 -- drivers/s390/cio/vfio_ccw_private.h | 3 ++- 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_dr= v.c index a10cec0e86eb..0b3b9de45c60 100644 --- a/drivers/s390/cio/vfio_ccw_drv.c +++ b/drivers/s390/cio/vfio_ccw_drv.c @@ -72,20 +72,24 @@ static void vfio_ccw_sch_io_todo(struct work_struct *wo= rk) { struct vfio_ccw_private *private; struct irb *irb; + bool is_final; =20 private =3D container_of(work, struct vfio_ccw_private, io_work); irb =3D &private->irb; =20 + is_final =3D !(scsw_actl(&irb->scsw) & + (SCSW_ACTL_DEVACT | SCSW_ACTL_SCHACT)); if (scsw_is_solicited(&irb->scsw)) { cp_update_scsw(&private->cp, &irb->scsw); - cp_free(&private->cp); + if (is_final) + cp_free(&private->cp); } memcpy(private->io_region->irb_area, irb, sizeof(*irb)); =20 if (private->io_trigger) eventfd_signal(private->io_trigger, 1); =20 - if (private->mdev) + if (private->mdev && is_final) private->state =3D VFIO_CCW_STATE_IDLE; } =20 diff --git a/drivers/s390/cio/vfio_ccw_fsm.c b/drivers/s390/cio/vfio_ccw_fs= m.c index e7c9877c9f1e..b4a141fbd1a8 100644 --- a/drivers/s390/cio/vfio_ccw_fsm.c +++ b/drivers/s390/cio/vfio_ccw_fsm.c @@ -28,7 +28,6 @@ static int fsm_io_helper(struct vfio_ccw_private *private) sch =3D private->sch; =20 spin_lock_irqsave(sch->lock, flags); - private->state =3D VFIO_CCW_STATE_BUSY; =20 orb =3D cp_get_orb(&private->cp, (u32)(addr_t)sch, sch->lpm); if (!orb) { @@ -46,6 +45,7 @@ static int fsm_io_helper(struct vfio_ccw_private *private) */ sch->schib.scsw.cmd.actl |=3D SCSW_ACTL_START_PEND; ret =3D 0; + private->state =3D VFIO_CCW_STATE_CP_PENDING; break; case 1: /* Status pending */ case 2: /* Busy */ @@ -107,6 +107,12 @@ static void fsm_io_busy(struct vfio_ccw_private *priva= te, private->io_region->ret_code =3D -EBUSY; } =20 +static void fsm_io_retry(struct vfio_ccw_private *private, + enum vfio_ccw_event event) +{ + private->io_region->ret_code =3D -EAGAIN; +} + static void fsm_disabled_irq(struct vfio_ccw_private *private, enum vfio_ccw_event event) { @@ -135,8 +141,7 @@ static void fsm_io_request(struct vfio_ccw_private *pri= vate, struct mdev_device *mdev =3D private->mdev; char *errstr =3D "request"; =20 - private->state =3D VFIO_CCW_STATE_BUSY; - + private->state =3D VFIO_CCW_STATE_CP_PROCESSING; memcpy(scsw, io_region->scsw_area, sizeof(*scsw)); =20 if (scsw->cmd.fctl & SCSW_FCTL_START_FUNC) { @@ -181,7 +186,6 @@ static void fsm_io_request(struct vfio_ccw_private *pri= vate, } =20 err_out: - private->state =3D VFIO_CCW_STATE_IDLE; trace_vfio_ccw_io_fctl(scsw->cmd.fctl, get_schid(private), io_region->ret_code, errstr); } @@ -221,7 +225,12 @@ fsm_func_t *vfio_ccw_jumptable[NR_VFIO_CCW_STATES][NR_= VFIO_CCW_EVENTS] =3D { [VFIO_CCW_EVENT_IO_REQ] =3D fsm_io_request, [VFIO_CCW_EVENT_INTERRUPT] =3D fsm_irq, }, - [VFIO_CCW_STATE_BUSY] =3D { + [VFIO_CCW_STATE_CP_PROCESSING] =3D { + [VFIO_CCW_EVENT_NOT_OPER] =3D fsm_notoper, + [VFIO_CCW_EVENT_IO_REQ] =3D fsm_io_retry, + [VFIO_CCW_EVENT_INTERRUPT] =3D fsm_irq, + }, + [VFIO_CCW_STATE_CP_PENDING] =3D { [VFIO_CCW_EVENT_NOT_OPER] =3D fsm_notoper, [VFIO_CCW_EVENT_IO_REQ] =3D fsm_io_busy, [VFIO_CCW_EVENT_INTERRUPT] =3D fsm_irq, diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_op= s.c index f673e106c041..3fdcc6dfe0bf 100644 --- a/drivers/s390/cio/vfio_ccw_ops.c +++ b/drivers/s390/cio/vfio_ccw_ops.c @@ -193,8 +193,6 @@ static ssize_t vfio_ccw_mdev_write(struct mdev_device *= mdev, return -EINVAL; =20 private =3D dev_get_drvdata(mdev_parent_dev(mdev)); - if (private->state !=3D VFIO_CCW_STATE_IDLE) - return -EACCES; =20 region =3D private->io_region; if (copy_from_user((void *)region + *ppos, buf, count)) diff --git a/drivers/s390/cio/vfio_ccw_private.h b/drivers/s390/cio/vfio_cc= w_private.h index 08e9a7dc9176..50c52efb4fcb 100644 --- a/drivers/s390/cio/vfio_ccw_private.h +++ b/drivers/s390/cio/vfio_ccw_private.h @@ -63,7 +63,8 @@ enum vfio_ccw_state { VFIO_CCW_STATE_NOT_OPER, VFIO_CCW_STATE_STANDBY, VFIO_CCW_STATE_IDLE, - VFIO_CCW_STATE_BUSY, + VFIO_CCW_STATE_CP_PROCESSING, + VFIO_CCW_STATE_CP_PENDING, /* last element! */ NR_VFIO_CCW_STATES }; --=20 2.17.2